@misoto22/design 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/article.css +393 -0
- package/dist/components/AppShell/AppShell.d.ts +15 -1
- package/dist/components/AppShell/AppShell.js +8 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +51 -0
- package/dist/components/Article/Article.js +21 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/Button/Button.js +2 -2
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Calendar/Calendar.js +259 -24
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.d.ts +15 -1
- package/dist/components/Collapsible/Collapsible.js +18 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.js +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.js +7 -7
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js +2 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/Diagram/Diagram.d.ts +81 -0
- package/dist/components/Diagram/Diagram.js +139 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.js +1 -1
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +2 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/FigureBand/FigureBand.js +41 -30
- package/dist/components/FigureBand/FigureBand.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Select/Select.js +2 -2
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Sheet/Sheet.js +1 -1
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Slider/Slider.js +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +55 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.js +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/useSelectionIndicator.js +14 -10
- package/dist/lib/useSelectionIndicator.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/themes.css +53 -7
- package/dist/tokens.css +75 -10
- package/dist/tokens.d.ts +8 -0
- package/dist/tokens.js +53 -8
- package/dist/tokens.json +53 -8
- package/package.json +22 -19
|
@@ -26,7 +26,7 @@ function PopoverContent({
|
|
|
26
26
|
sideOffset,
|
|
27
27
|
"data-m22-animated": true,
|
|
28
28
|
className: cn(
|
|
29
|
-
"z-(--z-dropdown) w-72 rounded-(--radius) border border-(--
|
|
29
|
+
"z-(--z-dropdown) w-72 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-4 panel-blur",
|
|
30
30
|
"data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)",
|
|
31
31
|
className
|
|
32
32
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["'use client'\n\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport { X } from 'lucide-react'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/** Radix Popover root, trigger, anchor and close, as typed passthroughs. */\nexport const Popover = PopoverPrimitive.Root\nexport const PopoverTrigger = PopoverPrimitive.Trigger\nexport const PopoverAnchor = PopoverPrimitive.Anchor\nexport const PopoverClose = PopoverPrimitive.Close\n\nexport interface PopoverContentProps\n extends ComponentProps<typeof PopoverPrimitive.Content> {\n /** Names the panel for assistive tech. Required — a popover is a dialog. */\n label: string\n /** Show the top-end close control. */\n showClose?: boolean\n}\n\n/**\n * A panel anchored to a control, holding content the reader can interact with.\n *\n * The line against `Tooltip` is not visual, it is behavioural: a tooltip\n * describes and cannot be entered; a popover holds things you tab to. Anything\n * with a link, a field or a button in it is a popover, and putting that inside\n * a tooltip makes it unreachable — the tooltip closes as soon as focus tries to\n * move into it.\n *\n * Against `DropdownMenu`: a menu is a list of actions with menu semantics and\n * arrow-key navigation. A popover is free-form, and its contents Tab like the\n * rest of the page.\n *\n * @example\n * <Popover>\n * <PopoverTrigger asChild><Button variant=\"secondary\">Filters</Button></PopoverTrigger>\n * <PopoverContent label=\"Filters\">\n * <Field label=\"Status\"><Select>…</Select></Field>\n * </PopoverContent>\n * </Popover>\n */\nexport function PopoverContent({\n label,\n showClose = false,\n className,\n sideOffset = 8,\n children,\n ...rest\n}: PopoverContentProps) {\n const container = useOverlayContainer()\n\n return (\n <PopoverPrimitive.Portal container={container ?? undefined}>\n <PopoverPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n aria-label={label}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) w-72 rounded-(--radius) border border-(--
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["'use client'\n\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport { X } from 'lucide-react'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/** Radix Popover root, trigger, anchor and close, as typed passthroughs. */\nexport const Popover = PopoverPrimitive.Root\nexport const PopoverTrigger = PopoverPrimitive.Trigger\nexport const PopoverAnchor = PopoverPrimitive.Anchor\nexport const PopoverClose = PopoverPrimitive.Close\n\nexport interface PopoverContentProps\n extends ComponentProps<typeof PopoverPrimitive.Content> {\n /** Names the panel for assistive tech. Required — a popover is a dialog. */\n label: string\n /** Show the top-end close control. */\n showClose?: boolean\n}\n\n/**\n * A panel anchored to a control, holding content the reader can interact with.\n *\n * The line against `Tooltip` is not visual, it is behavioural: a tooltip\n * describes and cannot be entered; a popover holds things you tab to. Anything\n * with a link, a field or a button in it is a popover, and putting that inside\n * a tooltip makes it unreachable — the tooltip closes as soon as focus tries to\n * move into it.\n *\n * Against `DropdownMenu`: a menu is a list of actions with menu semantics and\n * arrow-key navigation. A popover is free-form, and its contents Tab like the\n * rest of the page.\n *\n * @example\n * <Popover>\n * <PopoverTrigger asChild><Button variant=\"secondary\">Filters</Button></PopoverTrigger>\n * <PopoverContent label=\"Filters\">\n * <Field label=\"Status\"><Select>…</Select></Field>\n * </PopoverContent>\n * </Popover>\n */\nexport function PopoverContent({\n label,\n showClose = false,\n className,\n sideOffset = 8,\n children,\n ...rest\n}: PopoverContentProps) {\n const container = useOverlayContainer()\n\n return (\n <PopoverPrimitive.Portal container={container ?? undefined}>\n <PopoverPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n aria-label={label}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) w-72 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-4 panel-blur',\n 'data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)',\n className,\n )}\n {...rest}\n >\n {children}\n {showClose && (\n <PopoverPrimitive.Close\n aria-label=\"Close\"\n className=\"absolute end-2 top-2 grid size-8 place-items-center rounded-(--radius-pill) text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:bg-(--stone) hover:text-(--ink)\"\n >\n <X size={14} strokeWidth={1.5} aria-hidden />\n </PopoverPrimitive.Close>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n )\n}\n\nexport default Popover\n"],"mappings":";AAuDM,SAmBM,KAnBN;AArDN,YAAY,sBAAsB;AAClC,SAAS,SAAS;AAElB,SAAS,UAAU;AACnB,SAAS,2BAA2B;AAG7B,MAAM,UAAU,iBAAiB;AACjC,MAAM,iBAAiB,iBAAiB;AACxC,MAAM,gBAAgB,iBAAiB;AACvC,MAAM,eAAe,iBAAiB;AA+BtC,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAAwB;AACtB,QAAM,YAAY,oBAAoB;AAEtC,SACE,oBAAC,iBAAiB,QAAjB,EAAwB,WAAW,aAAa,QAC/C;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,mBAAmB,aAAa;AAAA,MAChC,kBAAkB;AAAA,MAClB,cAAY;AAAA,MACZ;AAAA,MACA,qBAAiB;AAAA,MACjB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACA,aACC;AAAA,UAAC,iBAAiB;AAAA,UAAjB;AAAA,YACC,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,8BAAC,KAAE,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC;AAAA;AAAA,QAC7C;AAAA;AAAA;AAAA,EAEJ,GACF;AAEJ;AAEA,IAAO,kBAAQ;","names":[]}
|
|
@@ -54,7 +54,7 @@ function Select({
|
|
|
54
54
|
sideOffset: 6,
|
|
55
55
|
"data-m22-animated": true,
|
|
56
56
|
className: cn(
|
|
57
|
-
"z-(--z-dropdown) max-h-72 min-w-(--radix-select-trigger-width) overflow-hidden rounded-(--radius) border border-(--
|
|
57
|
+
"z-(--z-dropdown) max-h-72 min-w-(--radix-select-trigger-width) overflow-hidden rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) panel-blur",
|
|
58
58
|
contentClassName,
|
|
59
59
|
"data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)"
|
|
60
60
|
),
|
|
@@ -72,7 +72,7 @@ function SelectItem({ className, children, ...props }) {
|
|
|
72
72
|
SelectPrimitive.Item,
|
|
73
73
|
{
|
|
74
74
|
className: cn(
|
|
75
|
-
"flex cursor-pointer select-none items-center gap-2.5 rounded-(--radius-
|
|
75
|
+
"flex cursor-pointer select-none items-center gap-2.5 rounded-(--radius-row) px-2.5 py-2 text-sm text-(--ink-2) outline-none transition-colors duration-(--duration-fast) data-[highlighted]:bg-(--stone) data-[highlighted]:text-(--ink) data-[disabled]:pointer-events-none data-[disabled]:opacity-(--disabled-opacity)",
|
|
76
76
|
className
|
|
77
77
|
),
|
|
78
78
|
...props,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["'use client'\n\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\nimport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from '../../lib/control'\n\n/** Radix Select root, group and label, as typed passthroughs. */\nexport const SelectRoot = SelectPrimitive.Root\nexport const SelectGroup = SelectPrimitive.Group\n\nexport interface SelectProps extends ComponentProps<typeof SelectPrimitive.Root> {\n /**\n * Classes for the option PANEL, not the trigger.\n *\n * `className` styles the trigger, which is the common case. This exists for\n * the uncommon one: a select inside a bounded surface, where the default\n * 18rem of list would cover the thing the reader is choosing for — a year\n * picker over its own calendar, say.\n */\n contentClassName?: string\n /** Names the control. Required — the trigger shows a value, and a value is not a name. */\n label: string\n placeholder?: string\n /** Paints the resting border with `--danger` and reflects `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n className?: string\n /** `SelectItem`s, optionally wrapped in `SelectGroup` with a `SelectLabel`. */\n children: ReactNode\n}\n\n/**\n * A choice from a list, styled the whole way down.\n *\n * The option list is ours — drawn from the same tokens as everything else, so\n * it does not change typeface, spacing and selection colour the moment it\n * opens. That is the whole reason this replaced the native control as the\n * default: a design system whose most common form control stops being part of\n * the system on click is not a design system, it is a stylesheet for closed\n * states.\n *\n * The keyboard contract is Radix's, which means it is the platform's: typeahead\n * works, the arrows move, Home and End reach the ends, and Escape closes\n * without choosing. That was the one genuine argument for staying native, and\n * it is answered.\n *\n * Past roughly a dozen options, reach for `Combobox` — a list nobody can filter\n * is worse than one they can type into. Where the platform picker is genuinely\n * better — a phone, or a form that must survive without JavaScript — reach for\n * `NativeSelect`.\n *\n * @example\n * <Field label=\"Region\">\n * <Select label=\"Region\" defaultValue=\"au\">\n * <SelectItem value=\"au\">Australia</SelectItem>\n * <SelectItem value=\"nz\">New Zealand</SelectItem>\n * </Select>\n * </Field>\n */\nexport function Select({\n label,\n placeholder = 'Select…',\n invalid,\n disabled,\n className,\n contentClassName,\n children,\n ...props\n}: SelectProps) {\n const bad = isInvalid(invalid)\n const container = useOverlayContainer()\n\n return (\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n aria-label={label}\n aria-invalid={bad || undefined}\n className={cn(\n CONTROL_BASE,\n 'group flex cursor-pointer items-center justify-between gap-2 text-start data-[placeholder]:text-(--ink-3-aa)',\n bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,\n className,\n )}\n >\n <SelectPrimitive.Value placeholder={placeholder} />\n <SelectPrimitive.Icon asChild>\n <ChevronDown\n size={16}\n strokeWidth={1.5}\n aria-hidden\n className=\"shrink-0 text-(--ink-3-aa) transition-transform duration-(--duration-fast) group-data-[state=open]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal container={container ?? undefined}>\n <SelectPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n position=\"popper\"\n sideOffset={6}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) max-h-72 min-w-(--radix-select-trigger-width) overflow-hidden rounded-(--radius) border border-(--
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["'use client'\n\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\nimport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from '../../lib/control'\n\n/** Radix Select root, group and label, as typed passthroughs. */\nexport const SelectRoot = SelectPrimitive.Root\nexport const SelectGroup = SelectPrimitive.Group\n\nexport interface SelectProps extends ComponentProps<typeof SelectPrimitive.Root> {\n /**\n * Classes for the option PANEL, not the trigger.\n *\n * `className` styles the trigger, which is the common case. This exists for\n * the uncommon one: a select inside a bounded surface, where the default\n * 18rem of list would cover the thing the reader is choosing for — a year\n * picker over its own calendar, say.\n */\n contentClassName?: string\n /** Names the control. Required — the trigger shows a value, and a value is not a name. */\n label: string\n placeholder?: string\n /** Paints the resting border with `--danger` and reflects `aria-invalid`. */\n invalid?: boolean\n disabled?: boolean\n className?: string\n /** `SelectItem`s, optionally wrapped in `SelectGroup` with a `SelectLabel`. */\n children: ReactNode\n}\n\n/**\n * A choice from a list, styled the whole way down.\n *\n * The option list is ours — drawn from the same tokens as everything else, so\n * it does not change typeface, spacing and selection colour the moment it\n * opens. That is the whole reason this replaced the native control as the\n * default: a design system whose most common form control stops being part of\n * the system on click is not a design system, it is a stylesheet for closed\n * states.\n *\n * The keyboard contract is Radix's, which means it is the platform's: typeahead\n * works, the arrows move, Home and End reach the ends, and Escape closes\n * without choosing. That was the one genuine argument for staying native, and\n * it is answered.\n *\n * Past roughly a dozen options, reach for `Combobox` — a list nobody can filter\n * is worse than one they can type into. Where the platform picker is genuinely\n * better — a phone, or a form that must survive without JavaScript — reach for\n * `NativeSelect`.\n *\n * @example\n * <Field label=\"Region\">\n * <Select label=\"Region\" defaultValue=\"au\">\n * <SelectItem value=\"au\">Australia</SelectItem>\n * <SelectItem value=\"nz\">New Zealand</SelectItem>\n * </Select>\n * </Field>\n */\nexport function Select({\n label,\n placeholder = 'Select…',\n invalid,\n disabled,\n className,\n contentClassName,\n children,\n ...props\n}: SelectProps) {\n const bad = isInvalid(invalid)\n const container = useOverlayContainer()\n\n return (\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n aria-label={label}\n aria-invalid={bad || undefined}\n className={cn(\n CONTROL_BASE,\n 'group flex cursor-pointer items-center justify-between gap-2 text-start data-[placeholder]:text-(--ink-3-aa)',\n bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,\n className,\n )}\n >\n <SelectPrimitive.Value placeholder={placeholder} />\n <SelectPrimitive.Icon asChild>\n <ChevronDown\n size={16}\n strokeWidth={1.5}\n aria-hidden\n className=\"shrink-0 text-(--ink-3-aa) transition-transform duration-(--duration-fast) group-data-[state=open]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal container={container ?? undefined}>\n <SelectPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n position=\"popper\"\n sideOffset={6}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) max-h-72 min-w-(--radix-select-trigger-width) overflow-hidden rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) panel-blur',\n contentClassName,\n 'data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)',\n )}\n >\n <SelectPrimitive.ScrollUpButton className=\"flex h-6 items-center justify-center text-(--ink-3-aa)\">\n <ChevronUp size={14} strokeWidth={1.5} aria-hidden />\n </SelectPrimitive.ScrollUpButton>\n <SelectPrimitive.Viewport className=\"p-1.5\">{children}</SelectPrimitive.Viewport>\n <SelectPrimitive.ScrollDownButton className=\"flex h-6 items-center justify-center text-(--ink-3-aa)\">\n <ChevronDown size={14} strokeWidth={1.5} aria-hidden />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n )\n}\n\nexport type SelectItemProps = ComponentProps<typeof SelectPrimitive.Item>\n\n/** One option. The tick marks the chosen one; the fill marks the highlighted one. */\nexport function SelectItem({ className, children, ...props }: SelectItemProps) {\n return (\n <SelectPrimitive.Item\n className={cn(\n 'flex cursor-pointer select-none items-center gap-2.5 rounded-(--radius-row) px-2.5 py-2 text-sm text-(--ink-2) outline-none transition-colors duration-(--duration-fast) data-[highlighted]:bg-(--stone) data-[highlighted]:text-(--ink) data-[disabled]:pointer-events-none data-[disabled]:opacity-(--disabled-opacity)',\n className,\n )}\n {...props}\n >\n {/* The box is always there and only the tick inside it appears, so\n choosing an option does not shunt every label sideways. */}\n <span className=\"grid size-3.5 shrink-0 place-items-center\">\n <SelectPrimitive.ItemIndicator asChild>\n <Check size={14} strokeWidth={2} aria-hidden />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\n/**\n * Mono eyebrow heading for a group of options.\n *\n * Must sit inside a `SelectGroup` — Radix throws otherwise, because a heading\n * with no group is a heading for nothing, and assistive tech would announce it\n * as an option.\n */\nexport function SelectLabel({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n className={cn('px-2.5 py-1.5 eyebrow text-(--ink-3-aa)', className)}\n {...props}\n />\n )\n}\n\n/** Hairline divider between groups. */\nexport function SelectSeparator({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator className={cn('my-1 h-px bg-(--rule)', className)} {...props} />\n )\n}\n\nexport default Select\n"],"mappings":";AA6EM,SAUE,KAVF;AA3EN,YAAY,qBAAqB;AACjC,SAAS,OAAO,aAAa,iBAAiB;AAE9C,SAAS,UAAU;AACnB,SAAS,2BAA2B;AACpC,SAAS,cAAc,gBAAgB,iBAAiB;AAGjD,MAAM,aAAa,gBAAgB;AACnC,MAAM,cAAc,gBAAgB;AAmDpC,SAAS,OAAO;AAAA,EACrB;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAgB;AACd,QAAM,MAAM,UAAU,OAAO;AAC7B,QAAM,YAAY,oBAAoB;AAEtC,SACE,qBAAC,gBAAgB,MAAhB,EAAqB,UAAqB,GAAG,OAC5C;AAAA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,cAAY;AAAA,QACZ,gBAAc,OAAO;AAAA,QACrB,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,MAAM,eAAe,UAAU,eAAe;AAAA,UAC9C;AAAA,QACF;AAAA,QAEA;AAAA,8BAAC,gBAAgB,OAAhB,EAAsB,aAA0B;AAAA,UACjD,oBAAC,gBAAgB,MAAhB,EAAqB,SAAO,MAC3B;AAAA,YAAC;AAAA;AAAA,cACC,MAAM;AAAA,cACN,aAAa;AAAA,cACb,eAAW;AAAA,cACX,WAAU;AAAA;AAAA,UACZ,GACF;AAAA;AAAA;AAAA,IACF;AAAA,IAEA,oBAAC,gBAAgB,QAAhB,EAAuB,WAAW,aAAa,QAC9C;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACD,mBAAmB,aAAa;AAAA,QAChC,kBAAkB;AAAA,QAChB,UAAS;AAAA,QACT,YAAY;AAAA,QACZ,qBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QAEA;AAAA,8BAAC,gBAAgB,gBAAhB,EAA+B,WAAU,0DACxC,8BAAC,aAAU,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC,GACrD;AAAA,UACA,oBAAC,gBAAgB,UAAhB,EAAyB,WAAU,SAAS,UAAS;AAAA,UACtD,oBAAC,gBAAgB,kBAAhB,EAAiC,WAAU,0DAC1C,8BAAC,eAAY,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC,GACvD;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;AAKO,SAAS,WAAW,EAAE,WAAW,UAAU,GAAG,MAAM,GAAoB;AAC7E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAIJ;AAAA,4BAAC,UAAK,WAAU,6CACd,8BAAC,gBAAgB,eAAhB,EAA8B,SAAO,MACpC,8BAAC,SAAM,MAAM,IAAI,aAAa,GAAG,eAAW,MAAC,GAC/C,GACF;AAAA,QACA,oBAAC,gBAAgB,UAAhB,EAA0B,UAAS;AAAA;AAAA;AAAA,EACtC;AAEJ;AASO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,GAAG;AACL,GAAiD;AAC/C,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,WAAW,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,GAAG;AACL,GAAqD;AACnD,SACE,oBAAC,gBAAgB,WAAhB,EAA0B,WAAW,GAAG,yBAAyB,SAAS,GAAI,GAAG,OAAO;AAE7F;AAEA,IAAO,iBAAQ;","names":[]}
|
|
@@ -33,7 +33,7 @@ function SheetContent({
|
|
|
33
33
|
DialogPrimitive.Content,
|
|
34
34
|
{
|
|
35
35
|
className: cn(
|
|
36
|
-
"fixed z-(--z-modal) flex flex-col overflow-y-auto border-(--
|
|
36
|
+
"fixed z-(--z-modal) flex flex-col overflow-y-auto border-(--panel-border) bg-(--panel-bg) p-6 panel-blur transition-transform duration-(--duration-slow) ease-(--ease-out-expo) scroll-slim",
|
|
37
37
|
SIDE[side],
|
|
38
38
|
className
|
|
39
39
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Sheet/Sheet.tsx"],"sourcesContent":["'use client'\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Dialog root, trigger and close — a sheet IS a dialog, docked. */\nexport const Sheet = DialogPrimitive.Root\nexport const SheetTrigger = DialogPrimitive.Trigger\nexport const SheetClose = DialogPrimitive.Close\n\nexport type SheetSide = 'start' | 'end' | 'top' | 'bottom'\n\n/**\n * Full literal class strings per edge, because Tailwind only generates what it\n * can see verbatim. The inline sides are named in READING order, so a sheet\n * docked to `end` comes from the right in English and the left in Arabic.\n */\nconst SIDE: Record<SheetSide, string> = {\n start:\n 'inset-y-0 start-0 h-full w-[min(24rem,92vw)] border-e data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full',\n end: 'inset-y-0 end-0 h-full w-[min(24rem,92vw)] border-s data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full',\n top: 'inset-x-0 top-0 w-full max-h-[85vh] border-b data-[state=closed]:-translate-y-full',\n bottom:\n 'inset-x-0 bottom-0 w-full max-h-[85vh] border-t data-[state=closed]:translate-y-full',\n}\n\nexport interface SheetContentProps\n extends Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title'> {\n /** Which edge it is docked to. `end` by default. */\n side?: SheetSide\n title: ReactNode\n description?: ReactNode\n /** Hide the title visually while keeping it for assistive tech. */\n hideTitle?: boolean\n}\n\n/**\n * A panel docked to an edge of the viewport.\n *\n * It is a modal dialog — Radix's, so the focus trap, the escape key, the scroll\n * lock and the `aria-modal` wiring are the same ones `Dialog` gets. The only\n * differences are where it sits and which way it arrives, which is why this\n * shares that implementation rather than reproducing it: a second focus trap is\n * a second focus trap to get wrong.\n *\n * The title is required, visible or not. A modal with no accessible name drops\n * a screen reader into an unnamed region with no way back out.\n *\n * @example\n * <Sheet>\n * <SheetTrigger asChild><Button variant=\"secondary\">Filters</Button></SheetTrigger>\n * <SheetContent title=\"Filters\" description=\"Narrow the list.\">…</SheetContent>\n * </Sheet>\n */\nexport function SheetContent({\n side = 'end',\n title,\n description,\n hideTitle = false,\n className,\n children,\n ...rest\n}: SheetContentProps) {\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay\n data-m22-animated\n className=\"fixed inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]\"\n />\n <DialogPrimitive.Content\n className={cn(\n 'fixed z-(--z-modal) flex flex-col overflow-y-auto border-(--
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Sheet/Sheet.tsx"],"sourcesContent":["'use client'\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Dialog root, trigger and close — a sheet IS a dialog, docked. */\nexport const Sheet = DialogPrimitive.Root\nexport const SheetTrigger = DialogPrimitive.Trigger\nexport const SheetClose = DialogPrimitive.Close\n\nexport type SheetSide = 'start' | 'end' | 'top' | 'bottom'\n\n/**\n * Full literal class strings per edge, because Tailwind only generates what it\n * can see verbatim. The inline sides are named in READING order, so a sheet\n * docked to `end` comes from the right in English and the left in Arabic.\n */\nconst SIDE: Record<SheetSide, string> = {\n start:\n 'inset-y-0 start-0 h-full w-[min(24rem,92vw)] border-e data-[state=closed]:-translate-x-full rtl:data-[state=closed]:translate-x-full',\n end: 'inset-y-0 end-0 h-full w-[min(24rem,92vw)] border-s data-[state=closed]:translate-x-full rtl:data-[state=closed]:-translate-x-full',\n top: 'inset-x-0 top-0 w-full max-h-[85vh] border-b data-[state=closed]:-translate-y-full',\n bottom:\n 'inset-x-0 bottom-0 w-full max-h-[85vh] border-t data-[state=closed]:translate-y-full',\n}\n\nexport interface SheetContentProps\n extends Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title'> {\n /** Which edge it is docked to. `end` by default. */\n side?: SheetSide\n title: ReactNode\n description?: ReactNode\n /** Hide the title visually while keeping it for assistive tech. */\n hideTitle?: boolean\n}\n\n/**\n * A panel docked to an edge of the viewport.\n *\n * It is a modal dialog — Radix's, so the focus trap, the escape key, the scroll\n * lock and the `aria-modal` wiring are the same ones `Dialog` gets. The only\n * differences are where it sits and which way it arrives, which is why this\n * shares that implementation rather than reproducing it: a second focus trap is\n * a second focus trap to get wrong.\n *\n * The title is required, visible or not. A modal with no accessible name drops\n * a screen reader into an unnamed region with no way back out.\n *\n * @example\n * <Sheet>\n * <SheetTrigger asChild><Button variant=\"secondary\">Filters</Button></SheetTrigger>\n * <SheetContent title=\"Filters\" description=\"Narrow the list.\">…</SheetContent>\n * </Sheet>\n */\nexport function SheetContent({\n side = 'end',\n title,\n description,\n hideTitle = false,\n className,\n children,\n ...rest\n}: SheetContentProps) {\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay\n data-m22-animated\n className=\"fixed inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]\"\n />\n <DialogPrimitive.Content\n className={cn(\n 'fixed z-(--z-modal) flex flex-col overflow-y-auto border-(--panel-border) bg-(--panel-bg) p-6 panel-blur transition-transform duration-(--duration-slow) ease-(--ease-out-expo) scroll-slim',\n SIDE[side],\n className,\n )}\n {...rest}\n >\n <div className={cn('mb-4 flex flex-col gap-1 pe-8', hideTitle && 'sr-only')}>\n <DialogPrimitive.Title className=\"m-0 font-heading text-[length:var(--fs-item)] font-normal text-(--ink)\">\n {title}\n </DialogPrimitive.Title>\n {description !== undefined && (\n <DialogPrimitive.Description className=\"m-0 text-sm leading-relaxed text-(--ink-3-aa)\">\n {description}\n </DialogPrimitive.Description>\n )}\n </div>\n\n <DialogPrimitive.Close\n aria-label=\"Close\"\n className=\"absolute end-3 top-3 grid size-9 place-items-center rounded-(--radius-pill) text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:bg-(--stone) hover:text-(--ink)\"\n >\n <X size={16} strokeWidth={1.5} aria-hidden />\n </DialogPrimitive.Close>\n\n {children}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n )\n}\n\nexport default Sheet\n"],"mappings":";AAmEM,cAYE,YAZF;AAjEN,YAAY,qBAAqB;AACjC,SAAS,SAAS;AAElB,SAAS,UAAU;AAGZ,MAAM,QAAQ,gBAAgB;AAC9B,MAAM,eAAe,gBAAgB;AACrC,MAAM,aAAa,gBAAgB;AAS1C,MAAM,OAAkC;AAAA,EACtC,OACE;AAAA,EACF,KAAK;AAAA,EACL,KAAK;AAAA,EACL,QACE;AACJ;AA8BO,SAAS,aAAa;AAAA,EAC3B,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,SACE,qBAAC,gBAAgB,QAAhB,EACC;AAAA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,KAAK,IAAI;AAAA,UACT;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ;AAAA,+BAAC,SAAI,WAAW,GAAG,iCAAiC,aAAa,SAAS,GACxE;AAAA,gCAAC,gBAAgB,OAAhB,EAAsB,WAAU,0EAC9B,iBACH;AAAA,YACC,gBAAgB,UACf,oBAAC,gBAAgB,aAAhB,EAA4B,WAAU,iDACpC,uBACH;AAAA,aAEJ;AAAA,UAEA;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,cAAW;AAAA,cACX,WAAU;AAAA,cAEV,8BAAC,KAAE,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC;AAAA;AAAA,UAC7C;AAAA,UAEC;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAEA,IAAO,gBAAQ;","names":[]}
|
|
@@ -35,7 +35,7 @@ function Slider({
|
|
|
35
35
|
SliderPrimitive.Thumb,
|
|
36
36
|
{
|
|
37
37
|
"aria-label": names[index] ?? names[0],
|
|
38
|
-
className: "relative block size-4 rounded-
|
|
38
|
+
className: "relative block size-4 rounded-(--radius-pill) border border-(--accent) bg-(--paper) transition-[transform,background-color] duration-(--duration-fast) ease-(--ease-out-expo) before:absolute before:left-1/2 before:top-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] hover:scale-110 hover:bg-(--stone) active:scale-125 data-[state=active]:scale-125 disabled:opacity-(--disabled-opacity) motion-reduce:transition-none"
|
|
39
39
|
},
|
|
40
40
|
index
|
|
41
41
|
))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["'use client'\n\nimport * as SliderPrimitive from '@radix-ui/react-slider'\nimport { useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface SliderProps extends ComponentProps<typeof SliderPrimitive.Root> {\n /**\n * Names the control. Required: a slider with no name announces only a number,\n * and a number with no noun is not information.\n *\n * A range slider (two thumbs) needs one name per thumb — pass an array.\n */\n label: string | [string, string]\n /** Prints the current value beside the label. */\n showValue?: boolean\n /** Renders the value with a unit or a currency, e.g. `(n) => n + '%'`. */\n format?: (value: number) => string\n}\n\n/**\n * A value chosen along a range.\n *\n * Radix owns the keyboard contract — arrows step, Page keys jump, Home and End\n * reach the ends — and the ARIA that reports the value. What is here is the\n * look, and the labelling, which is the part a slider most often gets wrong: a\n * thumb that announces \"42\" and nothing else leaves a screen reader user with a\n * number and no idea what it measures.\n *\n * A 44px hit area sits invisibly around the 16px thumb, because a thumb sized\n * for the design is well under any pointer-target guideline.\n *\n * @example\n * <Slider label=\"Quality\" defaultValue={[80]} max={100} step={5} showValue format={(n) => `${n}%`} />\n */\nexport function Slider({\n label,\n showValue = false,\n format = String,\n className,\n onValueChange,\n ...props\n}: SliderProps) {\n const names = Array.isArray(label) ? label : [label]\n\n // Tracked here, not read off the props. An uncontrolled slider's\n // `defaultValue` never changes, so the printed figure sat at its starting\n // number while the thumb moved — the one thing `showValue` exists to avoid.\n const [uncontrolled, setUncontrolled] = useState<number[]>(props.defaultValue ?? [])\n const current = props.value ?? uncontrolled\n\n const handleChange = (next: number[]) => {\n if (props.value === undefined) setUncontrolled(next)\n onValueChange?.(next)\n }\n\n return (\n <div className={cn('flex w-full flex-col gap-3', className)}>\n {showValue && (\n <div className=\"flex items-baseline justify-between mono-meta text-(--ink-3-aa)\">\n <span>{names[0]}</span>\n <span className=\"tabular-nums text-(--ink)\">\n {current.map((value) => format(value)).join(' – ')}\n </span>\n </div>\n )}\n <SliderPrimitive.Root\n className=\"group relative flex w-full touch-none select-none items-center py-3\"\n onValueChange={handleChange}\n {...props}\n >\n <SliderPrimitive.Track className=\"relative h-1 w-full grow overflow-hidden rounded-(--radius-pill) bg-(--stone) transition-[height] duration-(--duration-fast) group-hover:h-1.5\">\n <SliderPrimitive.Range className=\"absolute h-full bg-(--accent)\" />\n </SliderPrimitive.Track>\n {current.map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n aria-label={names[index] ?? names[0]}\n // The visible thumb is 16px; the `before` pseudo-element widens the\n // hit area to 44px without changing what is drawn.\n // `transition-transform` and not `all`: the thumb's own position is\n // set by Radix as a `left` percentage, and transitioning that would\n // make it lag the pointer. Only the grow-on-grab is animated.\n className=\"relative block size-4 rounded-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["'use client'\n\nimport * as SliderPrimitive from '@radix-ui/react-slider'\nimport { useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface SliderProps extends ComponentProps<typeof SliderPrimitive.Root> {\n /**\n * Names the control. Required: a slider with no name announces only a number,\n * and a number with no noun is not information.\n *\n * A range slider (two thumbs) needs one name per thumb — pass an array.\n */\n label: string | [string, string]\n /** Prints the current value beside the label. */\n showValue?: boolean\n /** Renders the value with a unit or a currency, e.g. `(n) => n + '%'`. */\n format?: (value: number) => string\n}\n\n/**\n * A value chosen along a range.\n *\n * Radix owns the keyboard contract — arrows step, Page keys jump, Home and End\n * reach the ends — and the ARIA that reports the value. What is here is the\n * look, and the labelling, which is the part a slider most often gets wrong: a\n * thumb that announces \"42\" and nothing else leaves a screen reader user with a\n * number and no idea what it measures.\n *\n * A 44px hit area sits invisibly around the 16px thumb, because a thumb sized\n * for the design is well under any pointer-target guideline.\n *\n * @example\n * <Slider label=\"Quality\" defaultValue={[80]} max={100} step={5} showValue format={(n) => `${n}%`} />\n */\nexport function Slider({\n label,\n showValue = false,\n format = String,\n className,\n onValueChange,\n ...props\n}: SliderProps) {\n const names = Array.isArray(label) ? label : [label]\n\n // Tracked here, not read off the props. An uncontrolled slider's\n // `defaultValue` never changes, so the printed figure sat at its starting\n // number while the thumb moved — the one thing `showValue` exists to avoid.\n const [uncontrolled, setUncontrolled] = useState<number[]>(props.defaultValue ?? [])\n const current = props.value ?? uncontrolled\n\n const handleChange = (next: number[]) => {\n if (props.value === undefined) setUncontrolled(next)\n onValueChange?.(next)\n }\n\n return (\n <div className={cn('flex w-full flex-col gap-3', className)}>\n {showValue && (\n <div className=\"flex items-baseline justify-between mono-meta text-(--ink-3-aa)\">\n <span>{names[0]}</span>\n <span className=\"tabular-nums text-(--ink)\">\n {current.map((value) => format(value)).join(' – ')}\n </span>\n </div>\n )}\n <SliderPrimitive.Root\n className=\"group relative flex w-full touch-none select-none items-center py-3\"\n onValueChange={handleChange}\n {...props}\n >\n <SliderPrimitive.Track className=\"relative h-1 w-full grow overflow-hidden rounded-(--radius-pill) bg-(--stone) transition-[height] duration-(--duration-fast) group-hover:h-1.5\">\n <SliderPrimitive.Range className=\"absolute h-full bg-(--accent)\" />\n </SliderPrimitive.Track>\n {current.map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n aria-label={names[index] ?? names[0]}\n // The visible thumb is 16px; the `before` pseudo-element widens the\n // hit area to 44px without changing what is drawn.\n // `transition-transform` and not `all`: the thumb's own position is\n // set by Radix as a `left` percentage, and transitioning that would\n // make it lag the pointer. Only the grow-on-grab is animated.\n className=\"relative block size-4 rounded-(--radius-pill) border border-(--accent) bg-(--paper) transition-[transform,background-color] duration-(--duration-fast) ease-(--ease-out-expo) before:absolute before:left-1/2 before:top-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] hover:scale-110 hover:bg-(--stone) active:scale-125 data-[state=active]:scale-125 disabled:opacity-(--disabled-opacity) motion-reduce:transition-none\"\n />\n ))}\n </SliderPrimitive.Root>\n </div>\n )\n}\n\nexport default Slider\n"],"mappings":";AA2DQ,SACE,KADF;AAzDR,YAAY,qBAAqB;AACjC,SAAS,gBAAqC;AAC9C,SAAS,UAAU;AA+BZ,SAAS,OAAO;AAAA,EACrB;AAAA,EACA,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAgB;AACd,QAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAKnD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAmB,MAAM,gBAAgB,CAAC,CAAC;AACnF,QAAM,UAAU,MAAM,SAAS;AAE/B,QAAM,eAAe,CAAC,SAAmB;AACvC,QAAI,MAAM,UAAU,OAAW,iBAAgB,IAAI;AACnD,oBAAgB,IAAI;AAAA,EACtB;AAEA,SACE,qBAAC,SAAI,WAAW,GAAG,8BAA8B,SAAS,GACvD;AAAA,iBACC,qBAAC,SAAI,WAAU,mEACb;AAAA,0BAAC,UAAM,gBAAM,CAAC,GAAE;AAAA,MAChB,oBAAC,UAAK,WAAU,6BACb,kBAAQ,IAAI,CAAC,UAAU,OAAO,KAAK,CAAC,EAAE,KAAK,UAAK,GACnD;AAAA,OACF;AAAA,IAEF;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,WAAU;AAAA,QACV,eAAe;AAAA,QACd,GAAG;AAAA,QAEJ;AAAA,8BAAC,gBAAgB,OAAhB,EAAsB,WAAU,kJAC/B,8BAAC,gBAAgB,OAAhB,EAAsB,WAAU,iCAAgC,GACnE;AAAA,UACC,QAAQ,IAAI,CAAC,GAAG,UACf;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cAEC,cAAY,MAAM,KAAK,KAAK,MAAM,CAAC;AAAA,cAMnC,WAAU;AAAA;AAAA,YAPL;AAAA,UAQP,CACD;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAEA,IAAO,iBAAQ;","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface Step {
|
|
5
|
+
/** Stable key; also what a caller keys its own data by. */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** The step's name — a noun, not a sentence. */
|
|
8
|
+
title: string;
|
|
9
|
+
/** The quiet line under it: what it is made of, what it costs, what it uses. */
|
|
10
|
+
note?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* The step being described, filled rather than outlined.
|
|
13
|
+
*
|
|
14
|
+
* At most one. It marks where the sequence has GOT to, which is a fact about
|
|
15
|
+
* the process rather than a highlight — two filled markers say the reader is
|
|
16
|
+
* in two places at once.
|
|
17
|
+
*/
|
|
18
|
+
current?: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface StepsProps extends Omit<HTMLAttributes<HTMLOListElement>, 'children'> {
|
|
21
|
+
steps: Step[];
|
|
22
|
+
/** Names the sequence for assistive tech when no heading does. */
|
|
23
|
+
label?: string;
|
|
24
|
+
/**
|
|
25
|
+
* How the marker is drawn.
|
|
26
|
+
*
|
|
27
|
+
* `number` counts from one and is right for a pipeline, a recipe, a
|
|
28
|
+
* migration. `rule` drops the digit for a plain hairline node, which is what
|
|
29
|
+
* a sequence of states wants — "queued, running, done" is an order, not a
|
|
30
|
+
* numbered list.
|
|
31
|
+
*/
|
|
32
|
+
marker?: 'number' | 'rule';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A numbered sequence, as a rail.
|
|
36
|
+
*
|
|
37
|
+
* The shape a pipeline actually has: one thing after another, each with a name
|
|
38
|
+
* and a line of detail, and a rule running through them so the eye reads them
|
|
39
|
+
* as one process rather than as five unrelated rows. It is the figure a
|
|
40
|
+
* technical post reaches for most often after a diagram, and it is NOT a
|
|
41
|
+
* diagram — nothing branches, nothing points at anything, and drawing it with
|
|
42
|
+
* boxes and arrows says otherwise.
|
|
43
|
+
*
|
|
44
|
+
* The connector is drawn on the ITEM rather than as a full-height line behind
|
|
45
|
+
* the markers, so it starts under one and stops above the next instead of
|
|
46
|
+
* running through both — and so the last step has no tail hanging off it. That
|
|
47
|
+
* is the detail that separates a rail from a list with a border on it.
|
|
48
|
+
*
|
|
49
|
+
* An `<ol>`, because the order is the content. `aria-current="step"` marks the
|
|
50
|
+
* filled one, which is the only thing here a screen reader could not otherwise
|
|
51
|
+
* infer from the order it is read in.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* <Steps
|
|
55
|
+
* label="How an answer is built"
|
|
56
|
+
* steps={[
|
|
57
|
+
* { title: 'Corpus', note: 'Blog MDX · project database' },
|
|
58
|
+
* { title: 'Chunking', note: 'By heading · 300–800 tokens' },
|
|
59
|
+
* { title: 'Answer', note: 'Live citation panel', current: true },
|
|
60
|
+
* ]}
|
|
61
|
+
* />
|
|
62
|
+
*/
|
|
63
|
+
declare function Steps({ steps, label, marker, className, ...rest }: StepsProps): react.JSX.Element | null;
|
|
64
|
+
|
|
65
|
+
export { type Step, Steps, type StepsProps, Steps as default };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
function Steps({ steps, label, marker = "number", className, ...rest }) {
|
|
4
|
+
if (steps.length === 0) return null;
|
|
5
|
+
return /* @__PURE__ */ jsx(
|
|
6
|
+
"ol",
|
|
7
|
+
{
|
|
8
|
+
"aria-label": label,
|
|
9
|
+
className: cn("m-0 flex list-none flex-col p-0 [--step-size:2rem]", className),
|
|
10
|
+
...rest,
|
|
11
|
+
children: steps.map((step, index) => {
|
|
12
|
+
const last = index === steps.length - 1;
|
|
13
|
+
return /* @__PURE__ */ jsxs(
|
|
14
|
+
"li",
|
|
15
|
+
{
|
|
16
|
+
"aria-current": step.current ? "step" : void 0,
|
|
17
|
+
className: "relative flex gap-4 pb-7 last:pb-0",
|
|
18
|
+
children: [
|
|
19
|
+
!last && /* @__PURE__ */ jsx(
|
|
20
|
+
"span",
|
|
21
|
+
{
|
|
22
|
+
"aria-hidden": true,
|
|
23
|
+
className: "absolute start-[calc(var(--step-size)/2)] top-(--step-size) bottom-0 w-px -translate-x-1/2 bg-(--rule-2) rtl:translate-x-1/2"
|
|
24
|
+
}
|
|
25
|
+
),
|
|
26
|
+
/* @__PURE__ */ jsx(
|
|
27
|
+
"span",
|
|
28
|
+
{
|
|
29
|
+
"aria-hidden": true,
|
|
30
|
+
className: cn(
|
|
31
|
+
"relative z-1 grid size-(--step-size) shrink-0 place-items-center rounded-full border text-[12px] tabular-nums",
|
|
32
|
+
step.current ? "border-(--accent) bg-(--accent) text-(--accent-foreground)" : "border-(--rule-2) bg-(--paper) text-(--ink-3-aa)",
|
|
33
|
+
marker === "rule" && "text-[0px]"
|
|
34
|
+
),
|
|
35
|
+
children: marker === "number" ? index + 1 : ""
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1 pt-1", children: [
|
|
39
|
+
/* @__PURE__ */ jsx("span", { className: "font-sans text-[15px] leading-tight text-(--ink)", children: step.title }),
|
|
40
|
+
step.note !== void 0 && step.note !== null && /* @__PURE__ */ jsx("span", { className: "mono-meta leading-[1.6] text-(--ink-3-aa)", children: step.note })
|
|
41
|
+
] })
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
step.id ?? `${step.title}-${index}`
|
|
45
|
+
);
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
var Steps_default = Steps;
|
|
51
|
+
export {
|
|
52
|
+
Steps,
|
|
53
|
+
Steps_default as default
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=Steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Steps/Steps.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface Step {\n /** Stable key; also what a caller keys its own data by. */\n id?: string\n /** The step's name — a noun, not a sentence. */\n title: string\n /** The quiet line under it: what it is made of, what it costs, what it uses. */\n note?: ReactNode\n /**\n * The step being described, filled rather than outlined.\n *\n * At most one. It marks where the sequence has GOT to, which is a fact about\n * the process rather than a highlight — two filled markers say the reader is\n * in two places at once.\n */\n current?: boolean\n}\n\nexport interface StepsProps extends Omit<HTMLAttributes<HTMLOListElement>, 'children'> {\n steps: Step[]\n /** Names the sequence for assistive tech when no heading does. */\n label?: string\n /**\n * How the marker is drawn.\n *\n * `number` counts from one and is right for a pipeline, a recipe, a\n * migration. `rule` drops the digit for a plain hairline node, which is what\n * a sequence of states wants — \"queued, running, done\" is an order, not a\n * numbered list.\n */\n marker?: 'number' | 'rule'\n}\n\n/**\n * A numbered sequence, as a rail.\n *\n * The shape a pipeline actually has: one thing after another, each with a name\n * and a line of detail, and a rule running through them so the eye reads them\n * as one process rather than as five unrelated rows. It is the figure a\n * technical post reaches for most often after a diagram, and it is NOT a\n * diagram — nothing branches, nothing points at anything, and drawing it with\n * boxes and arrows says otherwise.\n *\n * The connector is drawn on the ITEM rather than as a full-height line behind\n * the markers, so it starts under one and stops above the next instead of\n * running through both — and so the last step has no tail hanging off it. That\n * is the detail that separates a rail from a list with a border on it.\n *\n * An `<ol>`, because the order is the content. `aria-current=\"step\"` marks the\n * filled one, which is the only thing here a screen reader could not otherwise\n * infer from the order it is read in.\n *\n * @example\n * <Steps\n * label=\"How an answer is built\"\n * steps={[\n * { title: 'Corpus', note: 'Blog MDX · project database' },\n * { title: 'Chunking', note: 'By heading · 300–800 tokens' },\n * { title: 'Answer', note: 'Live citation panel', current: true },\n * ]}\n * />\n */\nexport function Steps({ steps, label, marker = 'number', className, ...rest }: StepsProps) {\n if (steps.length === 0) return null\n\n return (\n <ol\n aria-label={label}\n // One number for the marker, because three rules depend on it: the\n // marker's own box, where the connector starts, and where it is centred.\n // Written as a property rather than repeated as a literal so a caller can\n // move all three at once.\n className={cn('m-0 flex list-none flex-col p-0 [--step-size:2rem]', className)}\n {...rest}\n >\n {steps.map((step, index) => {\n const last = index === steps.length - 1\n return (\n <li\n key={step.id ?? `${step.title}-${index}`}\n aria-current={step.current ? 'step' : undefined}\n className=\"relative flex gap-4 pb-7 last:pb-0\"\n >\n {/* The connector. Absolute, so it spans the gap between this marker\n and the next without taking part in the row's own layout — and\n it is simply absent on the last row rather than drawn and then\n hidden. */}\n {!last && (\n <span\n aria-hidden\n className=\"absolute start-[calc(var(--step-size)/2)] top-(--step-size) bottom-0 w-px -translate-x-1/2 bg-(--rule-2) rtl:translate-x-1/2\"\n />\n )}\n <span\n aria-hidden\n className={cn(\n 'relative z-1 grid size-(--step-size) shrink-0 place-items-center rounded-full border text-[12px] tabular-nums',\n step.current\n ? 'border-(--accent) bg-(--accent) text-(--accent-foreground)'\n : 'border-(--rule-2) bg-(--paper) text-(--ink-3-aa)',\n marker === 'rule' && 'text-[0px]',\n )}\n >\n {marker === 'number' ? index + 1 : ''}\n </span>\n <div className=\"flex min-w-0 flex-col gap-1 pt-1\">\n <span className=\"font-sans text-[15px] leading-tight text-(--ink)\">{step.title}</span>\n {step.note !== undefined && step.note !== null && (\n <span className=\"mono-meta leading-[1.6] text-(--ink-3-aa)\">{step.note}</span>\n )}\n </div>\n </li>\n )\n })}\n </ol>\n )\n}\n\nexport default Steps\n"],"mappings":"AA0Fc,cAiBF,YAjBE;AAzFd,SAAS,UAAU;AA+DZ,SAAS,MAAM,EAAE,OAAO,OAAO,SAAS,UAAU,WAAW,GAAG,KAAK,GAAe;AACzF,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY;AAAA,MAKZ,WAAW,GAAG,sDAAsD,SAAS;AAAA,MAC5E,GAAG;AAAA,MAEH,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,cAAM,OAAO,UAAU,MAAM,SAAS;AACtC,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,gBAAc,KAAK,UAAU,SAAS;AAAA,YACtC,WAAU;AAAA,YAMT;AAAA,eAAC,QACA;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAU;AAAA;AAAA,cACZ;AAAA,cAEF;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAW;AAAA,oBACT;AAAA,oBACA,KAAK,UACD,+DACA;AAAA,oBACJ,WAAW,UAAU;AAAA,kBACvB;AAAA,kBAEC,qBAAW,WAAW,QAAQ,IAAI;AAAA;AAAA,cACrC;AAAA,cACA,qBAAC,SAAI,WAAU,oCACb;AAAA,oCAAC,UAAK,WAAU,oDAAoD,eAAK,OAAM;AAAA,gBAC9E,KAAK,SAAS,UAAa,KAAK,SAAS,QACxC,oBAAC,UAAK,WAAU,6CAA6C,eAAK,MAAK;AAAA,iBAE3E;AAAA;AAAA;AAAA,UA/BK,KAAK,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK;AAAA,QAgCxC;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,gBAAQ;","names":[]}
|
|
@@ -11,7 +11,7 @@ function Switch({ className, ...props }) {
|
|
|
11
11
|
className
|
|
12
12
|
),
|
|
13
13
|
...props,
|
|
14
|
-
children: /* @__PURE__ */ jsx(SwitchPrimitive.Thumb, { className: "block size-3.5 translate-x-0 rounded-
|
|
14
|
+
children: /* @__PURE__ */ jsx(SwitchPrimitive.Thumb, { className: "block size-3.5 translate-x-0 rounded-(--radius-pill) bg-(--paper) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) group-active:w-5 data-[state=checked]:translate-x-4 rtl:data-[state=checked]:-translate-x-4 motion-reduce:transition-none" })
|
|
15
15
|
}
|
|
16
16
|
);
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["'use client'\n\nimport * as SwitchPrimitive from '@radix-ui/react-switch'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport type SwitchProps = ComponentProps<typeof SwitchPrimitive.Root>\n\n/**\n * A setting that takes effect immediately.\n *\n * Distinct from `Checkbox`, and the distinction is not cosmetic: a switch\n * applies on flip, a checkbox applies on submit. A switch inside a form with a\n * Save button is a lie about when the change happened.\n *\n * The track fills with ink when on and the thumb is paper with a hairline —\n * rather than a white thumb floating on a drop shadow, which this system does\n * not have. The off state is a filled rule-coloured track, so the control still\n * reads as a control on a white page.\n *\n * @example\n * <Field label=\"Email notifications\"><Switch defaultChecked /></Field>\n */\nexport function Switch({ className, ...props }: SwitchProps) {\n return (\n <SwitchPrimitive.Root\n className={cn(\n 'group inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-(--radius-pill) border border-(--rule-2) bg-(--stone) px-0.5 transition-colors duration-(--duration-fast) hover:border-(--rule-hard) data-[state=checked]:border-(--accent) data-[state=checked]:bg-(--accent) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n className,\n )}\n {...props}\n >\n {/* The thumb narrows as it starts moving and rounds out again when it\n lands, which is what makes a 16px slide read as a deliberate flip\n rather than a jump. `transition-[transform,width]` and not `all`, so\n the track's own colour change keeps its shorter duration. */}\n <SwitchPrimitive.Thumb className=\"block size-3.5 translate-x-0 rounded-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["'use client'\n\nimport * as SwitchPrimitive from '@radix-ui/react-switch'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport type SwitchProps = ComponentProps<typeof SwitchPrimitive.Root>\n\n/**\n * A setting that takes effect immediately.\n *\n * Distinct from `Checkbox`, and the distinction is not cosmetic: a switch\n * applies on flip, a checkbox applies on submit. A switch inside a form with a\n * Save button is a lie about when the change happened.\n *\n * The track fills with ink when on and the thumb is paper with a hairline —\n * rather than a white thumb floating on a drop shadow, which this system does\n * not have. The off state is a filled rule-coloured track, so the control still\n * reads as a control on a white page.\n *\n * @example\n * <Field label=\"Email notifications\"><Switch defaultChecked /></Field>\n */\nexport function Switch({ className, ...props }: SwitchProps) {\n return (\n <SwitchPrimitive.Root\n className={cn(\n 'group inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-(--radius-pill) border border-(--rule-2) bg-(--stone) px-0.5 transition-colors duration-(--duration-fast) hover:border-(--rule-hard) data-[state=checked]:border-(--accent) data-[state=checked]:bg-(--accent) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n className,\n )}\n {...props}\n >\n {/* The thumb narrows as it starts moving and rounds out again when it\n lands, which is what makes a 16px slide read as a deliberate flip\n rather than a jump. `transition-[transform,width]` and not `all`, so\n the track's own colour change keeps its shorter duration. */}\n <SwitchPrimitive.Thumb className=\"block size-3.5 translate-x-0 rounded-(--radius-pill) bg-(--paper) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) group-active:w-5 data-[state=checked]:translate-x-4 rtl:data-[state=checked]:-translate-x-4 motion-reduce:transition-none\" />\n </SwitchPrimitive.Root>\n )\n}\n\nexport default Switch\n"],"mappings":";AAoCM;AAlCN,YAAY,qBAAqB;AAEjC,SAAS,UAAU;AAmBZ,SAAS,OAAO,EAAE,WAAW,GAAG,MAAM,GAAgB;AAC3D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAMJ,8BAAC,gBAAgB,OAAhB,EAAsB,WAAU,8QAA6Q;AAAA;AAAA,EAChT;AAEJ;AAEA,IAAO,iBAAQ;","names":[]}
|
|
@@ -23,7 +23,7 @@ function Tooltip({
|
|
|
23
23
|
sideOffset,
|
|
24
24
|
"data-m22-animated": true,
|
|
25
25
|
className: cn(
|
|
26
|
-
"z-(--z-toast) max-w-64 rounded-(--radius
|
|
26
|
+
"z-(--z-toast) max-w-64 rounded-(--radius) bg-(--feature-surface) px-2.5 py-1.5 font-mono text-[11px] leading-snug text-(--on-feature)",
|
|
27
27
|
"data-[state=delayed-open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]"
|
|
28
28
|
),
|
|
29
29
|
children: content
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/**\n * Wrap the app — or the smallest subtree that has tooltips — once. Radix needs\n * it to share the open/close timing between neighbouring triggers, which is\n * what stops a row of icon buttons flashing a tooltip per hover.\n */\nexport const TooltipProvider = TooltipPrimitive.Provider\n\nexport interface TooltipProps\n extends Pick<ComponentProps<typeof TooltipPrimitive.Root>, 'open' | 'defaultOpen' | 'onOpenChange' | 'delayDuration'> {\n /** The element the tooltip describes. Must be focusable. */\n children: ReactNode\n /**\n * The tip. Keep it to a phrase — a tooltip is unreachable on touch and\n * invisible to a reader who is scanning, so anything a user NEEDS belongs on\n * the page instead.\n */\n content: ReactNode\n side?: ComponentProps<typeof TooltipPrimitive.Content>['side']\n sideOffset?: number\n}\n\n/**\n * A short label on hover and on focus.\n *\n * `asChild` on the trigger by design: the tooltip must not add a wrapper that\n * swallows the trigger's own focus ring or breaks a flex row. It also means the\n * child has to be focusable — a `<div>` trigger gets no keyboard tooltip, which\n * is the failure this API shape makes obvious rather than silent.\n *\n * Not a replacement for an accessible name. An icon-only button still needs its\n * own `aria-label`; the tooltip repeats that name for sighted pointer users.\n *\n * @example\n * <TooltipProvider>\n * <Tooltip content=\"Copy to clipboard\">\n * <Button iconOnly aria-label=\"Copy\"><Copy size={16} /></Button>\n * </Tooltip>\n * </TooltipProvider>\n */\nexport function Tooltip({\n children,\n content,\n side = 'top',\n sideOffset = 6,\n ...root\n}: TooltipProps) {\n const container = useOverlayContainer()\n\n return (\n <TooltipPrimitive.Root {...root}>\n <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container ?? undefined}>\n <TooltipPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n side={side}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-toast) max-w-64 rounded-(--radius
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/**\n * Wrap the app — or the smallest subtree that has tooltips — once. Radix needs\n * it to share the open/close timing between neighbouring triggers, which is\n * what stops a row of icon buttons flashing a tooltip per hover.\n */\nexport const TooltipProvider = TooltipPrimitive.Provider\n\nexport interface TooltipProps\n extends Pick<ComponentProps<typeof TooltipPrimitive.Root>, 'open' | 'defaultOpen' | 'onOpenChange' | 'delayDuration'> {\n /** The element the tooltip describes. Must be focusable. */\n children: ReactNode\n /**\n * The tip. Keep it to a phrase — a tooltip is unreachable on touch and\n * invisible to a reader who is scanning, so anything a user NEEDS belongs on\n * the page instead.\n */\n content: ReactNode\n side?: ComponentProps<typeof TooltipPrimitive.Content>['side']\n sideOffset?: number\n}\n\n/**\n * A short label on hover and on focus.\n *\n * `asChild` on the trigger by design: the tooltip must not add a wrapper that\n * swallows the trigger's own focus ring or breaks a flex row. It also means the\n * child has to be focusable — a `<div>` trigger gets no keyboard tooltip, which\n * is the failure this API shape makes obvious rather than silent.\n *\n * Not a replacement for an accessible name. An icon-only button still needs its\n * own `aria-label`; the tooltip repeats that name for sighted pointer users.\n *\n * @example\n * <TooltipProvider>\n * <Tooltip content=\"Copy to clipboard\">\n * <Button iconOnly aria-label=\"Copy\"><Copy size={16} /></Button>\n * </Tooltip>\n * </TooltipProvider>\n */\nexport function Tooltip({\n children,\n content,\n side = 'top',\n sideOffset = 6,\n ...root\n}: TooltipProps) {\n const container = useOverlayContainer()\n\n return (\n <TooltipPrimitive.Root {...root}>\n <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container ?? undefined}>\n <TooltipPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n side={side}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-toast) max-w-64 rounded-(--radius) bg-(--feature-surface) px-2.5 py-1.5 font-mono text-[11px] leading-snug text-(--on-feature)',\n 'data-[state=delayed-open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]',\n )}\n >\n {content}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n )\n}\n\nexport default Tooltip\n"],"mappings":";AAwDI,SACE,KADF;AAtDJ,YAAY,sBAAsB;AAElC,SAAS,UAAU;AACnB,SAAS,2BAA2B;AAO7B,MAAM,kBAAkB,iBAAiB;AAkCzC,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,aAAa;AAAA,EACb,GAAG;AACL,GAAiB;AACf,QAAM,YAAY,oBAAoB;AAEtC,SACE,qBAAC,iBAAiB,MAAjB,EAAuB,GAAG,MACzB;AAAA,wBAAC,iBAAiB,SAAjB,EAAyB,SAAO,MAAE,UAAS;AAAA,IAC5C,oBAAC,iBAAiB,QAAjB,EAAwB,WAAW,aAAa,QAC/C;AAAA,MAAC,iBAAiB;AAAA,MAAjB;AAAA,QACD,mBAAmB,aAAa;AAAA,QAChC,kBAAkB;AAAA,QAChB;AAAA,QACA;AAAA,QACA,qBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QAEC;AAAA;AAAA,IACH,GACF;AAAA,KACF;AAEJ;AAEA,IAAO,kBAAQ;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export { Command, CommandDialog, CommandDialogProps, CommandEmpty, CommandFooter
|
|
|
43
43
|
export { MenuAction, SearchableMenu, SearchableMenuProps } from './components/SearchableMenu/SearchableMenu.js';
|
|
44
44
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from './components/Tabs/Tabs.js';
|
|
45
45
|
export { Accordion, AccordionItem, AccordionItemProps } from './components/Accordion/Accordion.js';
|
|
46
|
-
export { Collapsible, CollapsibleSection, CollapsibleSectionProps } from './components/Collapsible/Collapsible.js';
|
|
46
|
+
export { Collapsible, CollapsibleContent, CollapsibleSection, CollapsibleSectionProps, CollapsibleTrigger } from './components/Collapsible/Collapsible.js';
|
|
47
47
|
export { Breadcrumb, BreadcrumbProps, Crumb } from './components/Breadcrumb/Breadcrumb.js';
|
|
48
48
|
export { Pagination, PaginationProps, paginationRange } from './components/Pagination/Pagination.js';
|
|
49
49
|
export { NavItem, NavItemProps } from './components/NavItem/NavItem.js';
|
|
@@ -52,6 +52,9 @@ export { SortDirection, TBody, TD, TDProps, TH, THProps, THead, TR, Table, Table
|
|
|
52
52
|
export { Calendar, CalendarProps } from './components/Calendar/Calendar.js';
|
|
53
53
|
export { ScrollArea, ScrollAreaProps } from './components/ScrollArea/ScrollArea.js';
|
|
54
54
|
export { AppShell, AppShellProps } from './components/AppShell/AppShell.js';
|
|
55
|
+
export { Article, ArticleProps } from './components/Article/Article.js';
|
|
56
|
+
export { Diagram, DiagramEdge, DiagramNode, DiagramProps, DiagramSpec } from './components/Diagram/Diagram.js';
|
|
57
|
+
export { Step, Steps, StepsProps } from './components/Steps/Steps.js';
|
|
55
58
|
export { DateRange } from 'react-day-picker';
|
|
56
59
|
export { toast } from 'sonner';
|
|
57
60
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,9 @@ export * from "./components/Table/Table.js";
|
|
|
52
52
|
export * from "./components/Calendar/Calendar.js";
|
|
53
53
|
export * from "./components/ScrollArea/ScrollArea.js";
|
|
54
54
|
export * from "./components/AppShell/AppShell.js";
|
|
55
|
+
export * from "./components/Article/Article.js";
|
|
56
|
+
export * from "./components/Diagram/Diagram.js";
|
|
57
|
+
export * from "./components/Steps/Steps.js";
|
|
55
58
|
export {
|
|
56
59
|
BRAND,
|
|
57
60
|
CONTROL_BASE,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @misoto22/design — public entry.\n *\n * Components export from here; the look ships separately as CSS:\n *\n * import '@misoto22/design/styles.css' // compiled Tailwind + tokens + fonts\n *\n * or, for an app that already compiles Tailwind itself, the portable layers on\n * their own:\n *\n * import '@misoto22/design/tokens.css' // primitives\n * import '@misoto22/design/semantic.css' // roles\n * import '@misoto22/design/keyframes.css' // motion\n *\n * Everything below is a consumer contract. Adding an export is cheap; changing\n * or removing one is a breaking change (DESIGN-API-001).\n */\n\n// ─── Utilities ───\nexport * from './lib/overlay-container'\n\n// ─── Tokens ───\nexport { BRAND } from './tokens/brand'\nexport type { BrandColor } from './tokens/brand'\n\n// ─── Utilities ───\nexport { cn } from './lib/cn'\nexport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from './lib/control'\nexport { useSelectionIndicator } from './lib/useSelectionIndicator'\nexport type { IndicatorStyle } from './lib/useSelectionIndicator'\n\n// ─── Actions ───\nexport * from './components/Button/Button'\nexport * from './components/FloatingIconButton/FloatingIconButton'\n\n// ─── Display ───\nexport * from './components/Badge/Badge'\nexport * from './components/Tag/Tag'\nexport * from './components/Kbd/Kbd'\nexport * from './components/Avatar/Avatar'\nexport * from './components/StatusDot/StatusDot'\nexport * from './components/StatusPill/StatusPill'\nexport * from './components/LinkArrow/LinkArrow'\nexport * from './components/Separator/Separator'\nexport * from './components/FigureBand/FigureBand'\n\n// ─── Feedback ───\nexport * from './components/Spinner/Spinner'\nexport * from './components/Skeleton/Skeleton'\nexport * from './components/Progress/Progress'\nexport * from './components/Alert/Alert'\nexport * from './components/EmptyState/EmptyState'\nexport * from './components/ErrorState/ErrorState'\nexport * from './components/Toast/Toast'\n\n// ─── Forms ───\nexport * from './components/Field/Field'\nexport * from './components/Combobox/Combobox'\nexport * from './components/DatePicker/DatePicker'\nexport * from './components/Slider/Slider'\nexport * from './components/ToggleGroup/ToggleGroup'\nexport * from './components/Input/Input'\nexport * from './components/Textarea/Textarea'\nexport * from './components/Select/Select'\nexport * from './components/NativeSelect/NativeSelect'\nexport * from './components/Checkbox/Checkbox'\nexport * from './components/RadioGroup/RadioGroup'\nexport * from './components/Switch/Switch'\n\n// ─── Overlays ───\nexport * from './components/Dialog/Dialog'\nexport * from './components/DropdownMenu/DropdownMenu'\nexport * from './components/Tooltip/Tooltip'\nexport * from './components/Popover/Popover'\nexport * from './components/Sheet/Sheet'\nexport * from './components/ContextMenu/ContextMenu'\nexport * from './components/Command/Command'\nexport * from './components/SearchableMenu/SearchableMenu'\n\n// ─── Navigation ───\nexport * from './components/Tabs/Tabs'\nexport * from './components/Accordion/Accordion'\nexport * from './components/Collapsible/Collapsible'\nexport * from './components/Breadcrumb/Breadcrumb'\nexport * from './components/Pagination/Pagination'\nexport * from './components/NavItem/NavItem'\n\n// ─── Surfaces / layout ───\nexport * from './components/Card/Card'\nexport * from './components/Table/Table'\nexport * from './components/Calendar/Calendar'\nexport * from './components/ScrollArea/ScrollArea'\nexport * from './components/AppShell/AppShell'\n"],"mappings":"AAmBA,cAAc;AAGd,SAAS,aAAa;AAItB,SAAS,UAAU;AACnB,SAAS,cAAc,gBAAgB,iBAAiB;AACxD,SAAS,6BAA6B;AAItC,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @misoto22/design — public entry.\n *\n * Components export from here; the look ships separately as CSS:\n *\n * import '@misoto22/design/styles.css' // compiled Tailwind + tokens + fonts\n *\n * or, for an app that already compiles Tailwind itself, the portable layers on\n * their own:\n *\n * import '@misoto22/design/tokens.css' // primitives\n * import '@misoto22/design/semantic.css' // roles\n * import '@misoto22/design/keyframes.css' // motion\n *\n * Everything below is a consumer contract. Adding an export is cheap; changing\n * or removing one is a breaking change (DESIGN-API-001).\n */\n\n// ─── Utilities ───\nexport * from './lib/overlay-container'\n\n// ─── Tokens ───\nexport { BRAND } from './tokens/brand'\nexport type { BrandColor } from './tokens/brand'\n\n// ─── Utilities ───\nexport { cn } from './lib/cn'\nexport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from './lib/control'\nexport { useSelectionIndicator } from './lib/useSelectionIndicator'\nexport type { IndicatorStyle } from './lib/useSelectionIndicator'\n\n// ─── Actions ───\nexport * from './components/Button/Button'\nexport * from './components/FloatingIconButton/FloatingIconButton'\n\n// ─── Display ───\nexport * from './components/Badge/Badge'\nexport * from './components/Tag/Tag'\nexport * from './components/Kbd/Kbd'\nexport * from './components/Avatar/Avatar'\nexport * from './components/StatusDot/StatusDot'\nexport * from './components/StatusPill/StatusPill'\nexport * from './components/LinkArrow/LinkArrow'\nexport * from './components/Separator/Separator'\nexport * from './components/FigureBand/FigureBand'\n\n// ─── Feedback ───\nexport * from './components/Spinner/Spinner'\nexport * from './components/Skeleton/Skeleton'\nexport * from './components/Progress/Progress'\nexport * from './components/Alert/Alert'\nexport * from './components/EmptyState/EmptyState'\nexport * from './components/ErrorState/ErrorState'\nexport * from './components/Toast/Toast'\n\n// ─── Forms ───\nexport * from './components/Field/Field'\nexport * from './components/Combobox/Combobox'\nexport * from './components/DatePicker/DatePicker'\nexport * from './components/Slider/Slider'\nexport * from './components/ToggleGroup/ToggleGroup'\nexport * from './components/Input/Input'\nexport * from './components/Textarea/Textarea'\nexport * from './components/Select/Select'\nexport * from './components/NativeSelect/NativeSelect'\nexport * from './components/Checkbox/Checkbox'\nexport * from './components/RadioGroup/RadioGroup'\nexport * from './components/Switch/Switch'\n\n// ─── Overlays ───\nexport * from './components/Dialog/Dialog'\nexport * from './components/DropdownMenu/DropdownMenu'\nexport * from './components/Tooltip/Tooltip'\nexport * from './components/Popover/Popover'\nexport * from './components/Sheet/Sheet'\nexport * from './components/ContextMenu/ContextMenu'\nexport * from './components/Command/Command'\nexport * from './components/SearchableMenu/SearchableMenu'\n\n// ─── Navigation ───\nexport * from './components/Tabs/Tabs'\nexport * from './components/Accordion/Accordion'\nexport * from './components/Collapsible/Collapsible'\nexport * from './components/Breadcrumb/Breadcrumb'\nexport * from './components/Pagination/Pagination'\nexport * from './components/NavItem/NavItem'\n\n// ─── Surfaces / layout ───\nexport * from './components/Card/Card'\nexport * from './components/Table/Table'\nexport * from './components/Calendar/Calendar'\nexport * from './components/ScrollArea/ScrollArea'\nexport * from './components/AppShell/AppShell'\nexport * from './components/Article/Article'\nexport * from './components/Diagram/Diagram'\nexport * from './components/Steps/Steps'\n"],"mappings":"AAmBA,cAAc;AAGd,SAAS,aAAa;AAItB,SAAS,UAAU;AACnB,SAAS,cAAc,gBAAgB,iBAAiB;AACxD,SAAS,6BAA6B;AAItC,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -16,17 +16,21 @@ function useSelectionIndicator(key) {
|
|
|
16
16
|
setStyle((previous) => ({ ...previous, ready: false }));
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
let offset = 0;
|
|
20
|
+
let top = 0;
|
|
21
|
+
for (let node = selected; node && node !== container; node = node.offsetParent) {
|
|
22
|
+
offset += node.offsetLeft;
|
|
23
|
+
top += node.offsetTop;
|
|
24
|
+
}
|
|
21
25
|
setStyle({
|
|
22
|
-
// `left
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
offset
|
|
27
|
-
width:
|
|
28
|
-
height:
|
|
29
|
-
top
|
|
26
|
+
// Physical `left`, not `inline-start`: the pill is positioned with
|
|
27
|
+
// `transform`, which is physical, and the measurement has to match. It
|
|
28
|
+
// comes out right in both directions because both sides of the
|
|
29
|
+
// subtraction flip together.
|
|
30
|
+
offset,
|
|
31
|
+
width: selected.offsetWidth,
|
|
32
|
+
height: selected.offsetHeight,
|
|
33
|
+
top,
|
|
30
34
|
ready: true
|
|
31
35
|
});
|
|
32
36
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/useSelectionIndicator.ts"],"sourcesContent":["'use client'\n\nimport { useCallback, useLayoutEffect, useRef, useState } from 'react'\n\nexport interface IndicatorStyle {\n /** Distance from the container's inline start, in pixels. */\n offset: number\n width: number\n height: number\n top: number\n /** False until the first measurement, so the pill does not fly in from 0. */\n ready: boolean\n}\n\n/**\n * Measures the selected child so a single pill can slide between options\n * instead of one filled background switching off while another switches on.\n *\n * Why measure rather than animate each option's own background: a colour that\n * cross-fades reads as two things changing, and a shape that travels reads as\n * one thing moving — which is what actually happened. It is also the only way\n * to get the movement onto the compositor, since `background-color` cannot be\n * transformed.\n *\n * `useLayoutEffect` and not `useEffect`: the measurement has to land in the\n * same frame as the render that caused it, or the pill visibly starts from its\n * old place on first paint.\n *\n * Re-measures on resize and whenever `key` changes — `key` being whatever makes\n * the selection different, usually the selected value.\n */\nexport function useSelectionIndicator<T extends HTMLElement>(\n key: string | null,\n): [React.RefObject<T | null>, IndicatorStyle] {\n const containerRef = useRef<T>(null)\n const [style, setStyle] = useState<IndicatorStyle>({\n offset: 0,\n width: 0,\n height: 0,\n top: 0,\n ready: false,\n })\n\n const measure = useCallback(() => {\n const container = containerRef.current\n const selected = container?.querySelector<HTMLElement>('[data-indicator-active=\"true\"]')\n if (!container || !selected) {\n setStyle((previous) => ({ ...previous, ready: false }))\n return\n }\n
|
|
1
|
+
{"version":3,"sources":["../../src/lib/useSelectionIndicator.ts"],"sourcesContent":["'use client'\n\nimport { useCallback, useLayoutEffect, useRef, useState } from 'react'\n\nexport interface IndicatorStyle {\n /** Distance from the container's inline start, in pixels. */\n offset: number\n width: number\n height: number\n top: number\n /** False until the first measurement, so the pill does not fly in from 0. */\n ready: boolean\n}\n\n/**\n * Measures the selected child so a single pill can slide between options\n * instead of one filled background switching off while another switches on.\n *\n * Why measure rather than animate each option's own background: a colour that\n * cross-fades reads as two things changing, and a shape that travels reads as\n * one thing moving — which is what actually happened. It is also the only way\n * to get the movement onto the compositor, since `background-color` cannot be\n * transformed.\n *\n * `useLayoutEffect` and not `useEffect`: the measurement has to land in the\n * same frame as the render that caused it, or the pill visibly starts from its\n * old place on first paint.\n *\n * Re-measures on resize and whenever `key` changes — `key` being whatever makes\n * the selection different, usually the selected value.\n */\nexport function useSelectionIndicator<T extends HTMLElement>(\n key: string | null,\n): [React.RefObject<T | null>, IndicatorStyle] {\n const containerRef = useRef<T>(null)\n const [style, setStyle] = useState<IndicatorStyle>({\n offset: 0,\n width: 0,\n height: 0,\n top: 0,\n ready: false,\n })\n\n const measure = useCallback(() => {\n const container = containerRef.current\n const selected = container?.querySelector<HTMLElement>('[data-indicator-active=\"true\"]')\n if (!container || !selected) {\n setStyle((previous) => ({ ...previous, ready: false }))\n return\n }\n // `offsetLeft` and friends, not `getBoundingClientRect`.\n //\n // The rect is in VISUAL pixels: inside a zoomed or scaled ancestor — a\n // thumbnail, a device preview — it comes back multiplied, while the\n // `transform` this feeds is interpreted in the element's own coordinate\n // space. The pill then landed short of its segment by exactly the scale\n // factor. The offset properties are layout values and are unaffected.\n //\n // Offsets are relative to `offsetParent`, which is usually the strip itself\n // but need not be, so they are accumulated up to the container rather than\n // read once.\n let offset = 0\n let top = 0\n for (\n let node: HTMLElement | null = selected;\n node && node !== container;\n node = node.offsetParent as HTMLElement | null\n ) {\n offset += node.offsetLeft\n top += node.offsetTop\n }\n\n setStyle({\n // Physical `left`, not `inline-start`: the pill is positioned with\n // `transform`, which is physical, and the measurement has to match. It\n // comes out right in both directions because both sides of the\n // subtraction flip together.\n offset,\n width: selected.offsetWidth,\n height: selected.offsetHeight,\n top,\n ready: true,\n })\n }, [])\n\n useLayoutEffect(() => {\n measure()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(measure)\n if (containerRef.current) observer.observe(containerRef.current)\n return () => observer.disconnect()\n }, [key, measure])\n\n return [containerRef, style]\n}\n"],"mappings":";AAEA,SAAS,aAAa,iBAAiB,QAAQ,gBAAgB;AA6BxD,SAAS,sBACd,KAC6C;AAC7C,QAAM,eAAe,OAAU,IAAI;AACnC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAyB;AAAA,IACjD,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,YAAY,MAAM;AAChC,UAAM,YAAY,aAAa;AAC/B,UAAM,WAAW,WAAW,cAA2B,gCAAgC;AACvF,QAAI,CAAC,aAAa,CAAC,UAAU;AAC3B,eAAS,CAAC,cAAc,EAAE,GAAG,UAAU,OAAO,MAAM,EAAE;AACtD;AAAA,IACF;AAYA,QAAI,SAAS;AACb,QAAI,MAAM;AACV,aACM,OAA2B,UAC/B,QAAQ,SAAS,WACjB,OAAO,KAAK,cACZ;AACA,gBAAU,KAAK;AACf,aAAO,KAAK;AAAA,IACd;AAEA,aAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAKP;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,kBAAgB,MAAM;AACpB,YAAQ;AACR,QAAI,OAAO,mBAAmB,YAAa;AAC3C,UAAM,WAAW,IAAI,eAAe,OAAO;AAC3C,QAAI,aAAa,QAAS,UAAS,QAAQ,aAAa,OAAO;AAC/D,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,KAAK,OAAO,CAAC;AAEjB,SAAO,CAAC,cAAc,KAAK;AAC7B;","names":[]}
|