470 lines
17 KiB
JSON
470 lines
17 KiB
JSON
{
|
|
"plugins": [
|
|
"react",
|
|
"import"
|
|
],
|
|
"rules": {
|
|
"react/forbid-elements": [
|
|
"warn",
|
|
{
|
|
"forbid": []
|
|
}
|
|
],
|
|
"no-restricted-imports": [
|
|
"warn",
|
|
{
|
|
"patterns": [
|
|
{
|
|
"group": [
|
|
"components/data-display/**",
|
|
"components/feedback/**",
|
|
"components/forms/**",
|
|
"components/navigation/**",
|
|
"design_handoff_channel_builder/**"
|
|
],
|
|
"message": "Import design-system components from 'index.js', not component internals."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"no-restricted-syntax": [
|
|
"warn",
|
|
{
|
|
"selector": "Literal[value=/#[0-9a-fA-F]{3,8}\\b/]",
|
|
"message": "Raw hex color — use a design-system color token via var()."
|
|
},
|
|
{
|
|
"selector": "Literal[value=/\\b\\d+px\\b/]",
|
|
"message": "Raw px value — use a design-system spacing token via var()."
|
|
},
|
|
{
|
|
"selector": "Literal[value=/font-family\\s*:\\s*(?!['\\\"]?(?:Geist|Geist Mono))/i]",
|
|
"message": "Font not provided by the design system. Available: Geist, Geist Mono."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Badge'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|tone|solid|dot|style|key|ref|className|style|children)$/]",
|
|
"message": "<Badge> doesn't accept that prop. Declared props: children, tone, solid, dot, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Badge'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:neutral|accent|ok|warn|error)$/]",
|
|
"message": "<Badge> tone must be one of 'neutral' | 'accent' | 'ok' | 'warn' | 'error'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|variant|size|startIcon|endIcon|disabled|loading|fullWidth|type|onClick|style|key|ref|className|style|children)$/]",
|
|
"message": "<Button> doesn't accept that prop. Declared props: children, variant, size, startIcon, endIcon, disabled, loading, fullWidth, type, onClick, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='variant'] > Literal[value!=/^(?:primary|secondary|ghost|danger)$/]",
|
|
"message": "<Button> variant must be one of 'primary' | 'secondary' | 'ghost' | 'danger'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
|
|
"message": "<Button> size must be one of 'sm' | 'md'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='type'] > Literal[value!=/^(?:button|submit|reset)$/]",
|
|
"message": "<Button> type must be one of 'button' | 'submit' | 'reset'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Card'] > JSXAttribute > JSXIdentifier[name!=/^(?:title|subtitle|actions|children|padded|inset|style|key|ref|className|style|children)$/]",
|
|
"message": "<Card> doesn't accept that prop. Declared props: title, subtitle, actions, children, padded, inset, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='ChannelLogo'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|src|size|radius|style|key|ref|className|style|children)$/]",
|
|
"message": "<ChannelLogo> doesn't accept that prop. Declared props: name, src, size, radius, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Checkbox'] > JSXAttribute > JSXIdentifier[name!=/^(?:checked|onChange|label|indeterminate|disabled|style|key|ref|className|style|children)$/]",
|
|
"message": "<Checkbox> doesn't accept that prop. Declared props: checked, onChange, label, indeterminate, disabled, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='IconButton'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|size|variant|active|disabled|title|onClick|style|key|ref|className|style|children)$/]",
|
|
"message": "<IconButton> doesn't accept that prop. Declared props: children, size, variant, active, disabled, title, onClick, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='IconButton'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
|
|
"message": "<IconButton> size must be one of 'sm' | 'md'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='IconButton'] > JSXAttribute[name.name='variant'] > Literal[value!=/^(?:ghost|solid)$/]",
|
|
"message": "<IconButton> variant must be one of 'ghost' | 'solid'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute > JSXIdentifier[name!=/^(?:label|value|onChange|placeholder|leadingIcon|trailing|error|disabled|size|type|fullWidth|style|key|ref|className|style|children)$/]",
|
|
"message": "<Input> doesn't accept that prop. Declared props: label, value, onChange, placeholder, leadingIcon, trailing, error, disabled, size, type, fullWidth, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
|
|
"message": "<Input> size must be one of 'sm' | 'md'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='NavItem'] > JSXAttribute > JSXIdentifier[name!=/^(?:icon|label|active|badge|badgeTone|href|onClick|style|key|ref|className|style|children)$/]",
|
|
"message": "<NavItem> doesn't accept that prop. Declared props: icon, label, active, badge, badgeTone, href, onClick, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='NavItem'] > JSXAttribute[name.name='badgeTone'] > Literal[value!=/^(?:warn|error|accent)$/]",
|
|
"message": "<NavItem> badgeTone must be one of 'warn' | 'error' | 'accent'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='ProgressBar'] > JSXAttribute > JSXIdentifier[name!=/^(?:value|tone|height|showLabel|style|key|ref|className|style|children)$/]",
|
|
"message": "<ProgressBar> doesn't accept that prop. Declared props: value, tone, height, showLabel, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='ProgressBar'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:accent|ok|warn|error)$/]",
|
|
"message": "<ProgressBar> tone must be one of 'accent' | 'ok' | 'warn' | 'error'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='SelectOption'] > JSXAttribute > JSXIdentifier[name!=/^(?:value|label|key|ref|className|style|children)$/]",
|
|
"message": "<SelectOption> doesn't accept that prop. Declared props: value, label."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Spinner'] > JSXAttribute > JSXIdentifier[name!=/^(?:size|tone|stroke|style|key|ref|className|style|children)$/]",
|
|
"message": "<Spinner> doesn't accept that prop. Declared props: size, tone, stroke, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Spinner'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:accent|muted|ok)$/]",
|
|
"message": "<Spinner> tone must be one of 'accent' | 'muted' | 'ok'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Stat'] > JSXAttribute > JSXIdentifier[name!=/^(?:label|value|unit|delta|deltaTone|icon|style|key|ref|className|style|children)$/]",
|
|
"message": "<Stat> doesn't accept that prop. Declared props: label, value, unit, delta, deltaTone, icon, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Stat'] > JSXAttribute[name.name='deltaTone'] > Literal[value!=/^(?:up|down|neutral)$/]",
|
|
"message": "<Stat> deltaTone must be one of 'up' | 'down' | 'neutral'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='StatusDot'] > JSXAttribute > JSXIdentifier[name!=/^(?:status|pulse|size|label|style|key|ref|className|style|children)$/]",
|
|
"message": "<StatusDot> doesn't accept that prop. Declared props: status, pulse, size, label, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='StatusDot'] > JSXAttribute[name.name='status'] > Literal[value!=/^(?:live|ok|warn|error|idle)$/]",
|
|
"message": "<StatusDot> status must be one of 'live' | 'ok' | 'warn' | 'error' | 'idle'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Switch'] > JSXAttribute > JSXIdentifier[name!=/^(?:checked|onChange|label|disabled|size|style|key|ref|className|style|children)$/]",
|
|
"message": "<Switch> doesn't accept that prop. Declared props: checked, onChange, label, disabled, size, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Switch'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
|
|
"message": "<Switch> size must be one of 'sm' | 'md'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='TabItem'] > JSXAttribute > JSXIdentifier[name!=/^(?:value|label|icon|count|key|ref|className|style|children)$/]",
|
|
"message": "<TabItem> doesn't accept that prop. Declared props: value, label, icon, count."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|onRemove|icon|tone|style|key|ref|className|style|children)$/]",
|
|
"message": "<Tag> doesn't accept that prop. Declared props: children, onRemove, icon, tone, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:neutral|accent)$/]",
|
|
"message": "<Tag> tone must be one of 'neutral' | 'accent'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Toast'] > JSXAttribute > JSXIdentifier[name!=/^(?:tone|title|message|onClose|style|key|ref|className|style|children)$/]",
|
|
"message": "<Toast> doesn't accept that prop. Declared props: tone, title, message, onClose, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Toast'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:info|ok|warn|error)$/]",
|
|
"message": "<Toast> tone must be one of 'info' | 'ok' | 'warn' | 'error'."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Tooltip'] > JSXAttribute > JSXIdentifier[name!=/^(?:label|placement|children|style|key|ref|className|style|children)$/]",
|
|
"message": "<Tooltip> doesn't accept that prop. Declared props: label, placement, children, style."
|
|
},
|
|
{
|
|
"selector": "JSXOpeningElement[name.name='Tooltip'] > JSXAttribute[name.name='placement'] > Literal[value!=/^(?:top|bottom|left|right)$/]",
|
|
"message": "<Tooltip> placement must be one of 'top' | 'bottom' | 'left' | 'right'."
|
|
}
|
|
]
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": [
|
|
"**/index.js"
|
|
],
|
|
"rules": {
|
|
"no-restricted-imports": "off"
|
|
}
|
|
}
|
|
],
|
|
"x-omelette": {
|
|
"components": {
|
|
"Badge": {
|
|
"replaces": []
|
|
},
|
|
"Button": {
|
|
"replaces": []
|
|
},
|
|
"Card": {
|
|
"replaces": []
|
|
},
|
|
"ChannelLogo": {
|
|
"replaces": []
|
|
},
|
|
"Checkbox": {
|
|
"replaces": []
|
|
},
|
|
"IconButton": {
|
|
"replaces": []
|
|
},
|
|
"Input": {
|
|
"replaces": []
|
|
},
|
|
"NavItem": {
|
|
"replaces": []
|
|
},
|
|
"ProgressBar": {
|
|
"replaces": []
|
|
},
|
|
"SelectOption": {
|
|
"replaces": []
|
|
},
|
|
"Spinner": {
|
|
"replaces": []
|
|
},
|
|
"Stat": {
|
|
"replaces": []
|
|
},
|
|
"StatusDot": {
|
|
"replaces": []
|
|
},
|
|
"Switch": {
|
|
"replaces": []
|
|
},
|
|
"TabItem": {
|
|
"replaces": []
|
|
},
|
|
"Tag": {
|
|
"replaces": []
|
|
},
|
|
"Toast": {
|
|
"replaces": []
|
|
},
|
|
"Tooltip": {
|
|
"replaces": []
|
|
}
|
|
},
|
|
"tokens": [
|
|
"--action-primary",
|
|
"--action-primary-hover",
|
|
"--action-primary-press",
|
|
"--border-control",
|
|
"--border-hairline",
|
|
"--control-h",
|
|
"--control-h-sm",
|
|
"--ctv-accent",
|
|
"--ctv-accent-hover",
|
|
"--ctv-accent-press",
|
|
"--ctv-accent-ring",
|
|
"--ctv-accent-soft",
|
|
"--ctv-bg",
|
|
"--ctv-bg-sunken",
|
|
"--ctv-border",
|
|
"--ctv-border-strong",
|
|
"--ctv-error",
|
|
"--ctv-error-soft",
|
|
"--ctv-live",
|
|
"--ctv-live-soft",
|
|
"--ctv-ok",
|
|
"--ctv-ok-soft",
|
|
"--ctv-secondary",
|
|
"--ctv-secondary-soft",
|
|
"--ctv-surface",
|
|
"--ctv-surface-2",
|
|
"--ctv-surface-3",
|
|
"--ctv-text",
|
|
"--ctv-text-faint",
|
|
"--ctv-text-muted",
|
|
"--ctv-warn",
|
|
"--ctv-warn-soft",
|
|
"--dur-base",
|
|
"--dur-fast",
|
|
"--dur-slow",
|
|
"--ease-out",
|
|
"--ease-standard",
|
|
"--focus-ring",
|
|
"--font-mono",
|
|
"--font-sans",
|
|
"--gap-inline",
|
|
"--leading-normal",
|
|
"--leading-snug",
|
|
"--leading-tight",
|
|
"--numeric-feature",
|
|
"--pad-card",
|
|
"--pad-cell-x",
|
|
"--pad-cell-y",
|
|
"--pad-control-x",
|
|
"--pad-control-y",
|
|
"--pad-page",
|
|
"--radius-lg",
|
|
"--radius-md",
|
|
"--radius-pill",
|
|
"--radius-sm",
|
|
"--radius-xs",
|
|
"--ring-focus",
|
|
"--row-h",
|
|
"--shadow-lg",
|
|
"--shadow-md",
|
|
"--shadow-none",
|
|
"--shadow-pop",
|
|
"--shadow-sm",
|
|
"--sidebar-w",
|
|
"--space-0",
|
|
"--space-1",
|
|
"--space-10",
|
|
"--space-11",
|
|
"--space-12",
|
|
"--space-2",
|
|
"--space-3",
|
|
"--space-4",
|
|
"--space-5",
|
|
"--space-6",
|
|
"--space-7",
|
|
"--space-8",
|
|
"--space-9",
|
|
"--status-error",
|
|
"--status-live",
|
|
"--status-ok",
|
|
"--status-warn",
|
|
"--surface-app",
|
|
"--surface-card",
|
|
"--surface-raised",
|
|
"--surface-selected",
|
|
"--text-2xl",
|
|
"--text-2xs",
|
|
"--text-3xl",
|
|
"--text-disabled",
|
|
"--text-lg",
|
|
"--text-md",
|
|
"--text-on-accent",
|
|
"--text-primary",
|
|
"--text-secondary",
|
|
"--text-sm",
|
|
"--text-xl",
|
|
"--text-xs",
|
|
"--topbar-h",
|
|
"--tracking-caps",
|
|
"--tracking-normal",
|
|
"--tracking-tight",
|
|
"--tracking-wide",
|
|
"--weight-bold",
|
|
"--weight-medium",
|
|
"--weight-normal",
|
|
"--weight-semibold"
|
|
],
|
|
"tokenKinds": {
|
|
"--ctv-bg": "color",
|
|
"--ctv-bg-sunken": "color",
|
|
"--ctv-surface": "color",
|
|
"--ctv-surface-2": "color",
|
|
"--ctv-surface-3": "color",
|
|
"--ctv-border": "color",
|
|
"--ctv-border-strong": "color",
|
|
"--ctv-text": "font",
|
|
"--ctv-text-muted": "font",
|
|
"--ctv-text-faint": "font",
|
|
"--ctv-accent": "color",
|
|
"--ctv-accent-hover": "color",
|
|
"--ctv-accent-press": "color",
|
|
"--ctv-accent-soft": "color",
|
|
"--ctv-accent-ring": "color",
|
|
"--ctv-secondary": "color",
|
|
"--ctv-secondary-soft": "color",
|
|
"--ctv-ok": "color",
|
|
"--ctv-ok-soft": "color",
|
|
"--ctv-warn": "color",
|
|
"--ctv-warn-soft": "color",
|
|
"--ctv-error": "color",
|
|
"--ctv-error-soft": "color",
|
|
"--ctv-live": "color",
|
|
"--ctv-live-soft": "color",
|
|
"--surface-app": "color",
|
|
"--surface-card": "color",
|
|
"--surface-raised": "color",
|
|
"--surface-selected": "color",
|
|
"--border-hairline": "color",
|
|
"--border-control": "color",
|
|
"--text-primary": "font",
|
|
"--text-secondary": "font",
|
|
"--text-disabled": "font",
|
|
"--text-on-accent": "font",
|
|
"--action-primary": "color",
|
|
"--action-primary-hover": "color",
|
|
"--action-primary-press": "color",
|
|
"--focus-ring": "color",
|
|
"--status-ok": "color",
|
|
"--status-warn": "color",
|
|
"--status-error": "color",
|
|
"--status-live": "color",
|
|
"--font-sans": "font",
|
|
"--font-mono": "font",
|
|
"--text-2xs": "font",
|
|
"--text-xs": "font",
|
|
"--text-sm": "font",
|
|
"--text-md": "font",
|
|
"--text-lg": "font",
|
|
"--text-xl": "font",
|
|
"--text-2xl": "font",
|
|
"--text-3xl": "font",
|
|
"--weight-normal": "font",
|
|
"--weight-medium": "font",
|
|
"--weight-semibold": "font",
|
|
"--weight-bold": "font",
|
|
"--leading-tight": "font",
|
|
"--leading-snug": "font",
|
|
"--leading-normal": "font",
|
|
"--tracking-tight": "font",
|
|
"--tracking-normal": "font",
|
|
"--tracking-wide": "font",
|
|
"--tracking-caps": "font",
|
|
"--numeric-feature": "other",
|
|
"--space-0": "spacing",
|
|
"--space-1": "spacing",
|
|
"--space-2": "spacing",
|
|
"--space-3": "spacing",
|
|
"--space-4": "spacing",
|
|
"--space-5": "spacing",
|
|
"--space-6": "spacing",
|
|
"--space-7": "spacing",
|
|
"--space-8": "spacing",
|
|
"--space-9": "spacing",
|
|
"--space-10": "spacing",
|
|
"--space-11": "spacing",
|
|
"--space-12": "spacing",
|
|
"--gap-inline": "spacing",
|
|
"--pad-control-x": "spacing",
|
|
"--pad-control-y": "spacing",
|
|
"--pad-card": "spacing",
|
|
"--pad-cell-x": "spacing",
|
|
"--pad-cell-y": "spacing",
|
|
"--pad-page": "spacing",
|
|
"--sidebar-w": "spacing",
|
|
"--topbar-h": "spacing",
|
|
"--row-h": "spacing",
|
|
"--control-h": "spacing",
|
|
"--control-h-sm": "spacing",
|
|
"--radius-xs": "radius",
|
|
"--radius-sm": "radius",
|
|
"--radius-md": "radius",
|
|
"--radius-lg": "radius",
|
|
"--radius-pill": "radius",
|
|
"--shadow-none": "shadow",
|
|
"--shadow-sm": "shadow",
|
|
"--shadow-md": "shadow",
|
|
"--shadow-lg": "shadow",
|
|
"--shadow-pop": "shadow",
|
|
"--ring-focus": "color",
|
|
"--ease-standard": "other",
|
|
"--ease-out": "other",
|
|
"--dur-fast": "other",
|
|
"--dur-base": "other",
|
|
"--dur-slow": "other"
|
|
},
|
|
"fontFamilies": [
|
|
"Geist",
|
|
"Geist Mono"
|
|
]
|
|
}
|
|
} |