pendentive 0.1.1

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.
Files changed (113) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +88 -0
  3. package/dist/components/avatar/Avatar.d.ts +26 -0
  4. package/dist/components/badge/Badge.d.ts +25 -0
  5. package/dist/components/button/Button.d.ts +51 -0
  6. package/dist/components/button/ButtonGroup.d.ts +36 -0
  7. package/dist/components/checkbox/Checkbox.d.ts +34 -0
  8. package/dist/components/command/Command.d.ts +59 -0
  9. package/dist/components/data/List.d.ts +40 -0
  10. package/dist/components/data/Table.d.ts +37 -0
  11. package/dist/components/data/Tree.d.ts +36 -0
  12. package/dist/components/feedback/Alert.d.ts +29 -0
  13. package/dist/components/feedback/ProgressBar.d.ts +32 -0
  14. package/dist/components/feedback/Skeleton.d.ts +20 -0
  15. package/dist/components/feedback/Spinner.d.ts +20 -0
  16. package/dist/components/feedback/Toast.d.ts +30 -0
  17. package/dist/components/field/ColorField.d.ts +33 -0
  18. package/dist/components/field/NumberField.d.ts +42 -0
  19. package/dist/components/field/TextArea.d.ts +35 -0
  20. package/dist/components/field/TextField.d.ts +39 -0
  21. package/dist/components/field/shared.d.ts +9 -0
  22. package/dist/components/field/textInput.css.d.ts +5 -0
  23. package/dist/components/hovercard/HoverCard.d.ts +35 -0
  24. package/dist/components/input/ChipInput.d.ts +31 -0
  25. package/dist/components/input/DatePicker.d.ts +66 -0
  26. package/dist/components/input/FileDropzone.d.ts +26 -0
  27. package/dist/components/layout/Card.d.ts +24 -0
  28. package/dist/components/layout/Section.d.ts +33 -0
  29. package/dist/components/layout/Separator.d.ts +18 -0
  30. package/dist/components/misc/ModeCard.d.ts +35 -0
  31. package/dist/components/navigation/Accordion.d.ts +42 -0
  32. package/dist/components/navigation/Breadcrumb.d.ts +25 -0
  33. package/dist/components/navigation/Pagination.d.ts +30 -0
  34. package/dist/components/navigation/Tabs.d.ts +38 -0
  35. package/dist/components/overlay/AlertDialog.d.ts +37 -0
  36. package/dist/components/overlay/ContextMenu.d.ts +19 -0
  37. package/dist/components/overlay/Dialog.d.ts +38 -0
  38. package/dist/components/overlay/Drawer.d.ts +40 -0
  39. package/dist/components/overlay/DropdownMenu.d.ts +55 -0
  40. package/dist/components/overlay/Popover.d.ts +33 -0
  41. package/dist/components/radio/RadioGroup.d.ts +37 -0
  42. package/dist/components/select/Combobox.d.ts +42 -0
  43. package/dist/components/select/Select.d.ts +48 -0
  44. package/dist/components/slider/RangeSlider.d.ts +43 -0
  45. package/dist/components/slider/Slider.d.ts +41 -0
  46. package/dist/components/switch/Switch.d.ts +35 -0
  47. package/dist/components/toggle/Toggle.d.ts +39 -0
  48. package/dist/components/toggle/ToggleGroup.d.ts +47 -0
  49. package/dist/components/tooltip/Tooltip.d.ts +22 -0
  50. package/dist/core/classNames.d.ts +6 -0
  51. package/dist/core/content.d.ts +2 -0
  52. package/dist/core/controller.d.ts +34 -0
  53. package/dist/core/dom.d.ts +14 -0
  54. package/dist/core/overlay.d.ts +14 -0
  55. package/dist/core/styleInjector.d.ts +12 -0
  56. package/dist/core/theme.d.ts +18 -0
  57. package/dist/core/types.d.ts +10 -0
  58. package/dist/index.cjs +4054 -0
  59. package/dist/index.cjs.map +1 -0
  60. package/dist/index.d.ts +62 -0
  61. package/dist/index.js +3934 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/linteau.global.js +397 -0
  64. package/dist/linteau.global.js.map +7 -0
  65. package/dist/styles/tokens.d.ts +33 -0
  66. package/dist/svg/Icon.d.ts +19 -0
  67. package/dist/svg/create-icon.d.ts +13 -0
  68. package/dist/svg/icons/alertTriangle.d.ts +1 -0
  69. package/dist/svg/icons/bell.d.ts +1 -0
  70. package/dist/svg/icons/calendar.d.ts +1 -0
  71. package/dist/svg/icons/check.d.ts +1 -0
  72. package/dist/svg/icons/chevronDown.d.ts +1 -0
  73. package/dist/svg/icons/chevronLeft.d.ts +1 -0
  74. package/dist/svg/icons/chevronRight.d.ts +1 -0
  75. package/dist/svg/icons/chevronUp.d.ts +1 -0
  76. package/dist/svg/icons/circle.d.ts +1 -0
  77. package/dist/svg/icons/copy.d.ts +1 -0
  78. package/dist/svg/icons/download.d.ts +1 -0
  79. package/dist/svg/icons/edit.d.ts +1 -0
  80. package/dist/svg/icons/externalLink.d.ts +1 -0
  81. package/dist/svg/icons/eye.d.ts +1 -0
  82. package/dist/svg/icons/eyeOff.d.ts +1 -0
  83. package/dist/svg/icons/filter.d.ts +1 -0
  84. package/dist/svg/icons/heart.d.ts +1 -0
  85. package/dist/svg/icons/home.d.ts +1 -0
  86. package/dist/svg/icons/index.d.ts +54 -0
  87. package/dist/svg/icons/info.d.ts +1 -0
  88. package/dist/svg/icons/link.d.ts +1 -0
  89. package/dist/svg/icons/loader.d.ts +1 -0
  90. package/dist/svg/icons/lock.d.ts +1 -0
  91. package/dist/svg/icons/mail.d.ts +1 -0
  92. package/dist/svg/icons/menu.d.ts +1 -0
  93. package/dist/svg/icons/minus.d.ts +1 -0
  94. package/dist/svg/icons/moon.d.ts +1 -0
  95. package/dist/svg/icons/moreHorizontal.d.ts +1 -0
  96. package/dist/svg/icons/phone.d.ts +1 -0
  97. package/dist/svg/icons/plus.d.ts +1 -0
  98. package/dist/svg/icons/refreshCw.d.ts +1 -0
  99. package/dist/svg/icons/search.d.ts +1 -0
  100. package/dist/svg/icons/settings.d.ts +1 -0
  101. package/dist/svg/icons/star.d.ts +1 -0
  102. package/dist/svg/icons/sun.d.ts +1 -0
  103. package/dist/svg/icons/trash.d.ts +1 -0
  104. package/dist/svg/icons/upload.d.ts +1 -0
  105. package/dist/svg/icons/user.d.ts +1 -0
  106. package/dist/svg/icons/x.d.ts +1 -0
  107. package/dist/svg/index.cjs +380 -0
  108. package/dist/svg/index.cjs.map +1 -0
  109. package/dist/svg/index.d.ts +4 -0
  110. package/dist/svg/index.js +352 -0
  111. package/dist/svg/index.js.map +1 -0
  112. package/dist/svg/types.d.ts +26 -0
  113. package/package.json +81 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/dom.ts","../src/core/controller.ts","../src/styles/tokens.ts","../src/core/theme.ts","../src/svg/Icon.ts","../src/svg/create-icon.ts","../src/svg/icons/alertTriangle.ts","../src/svg/icons/bell.ts","../src/svg/icons/calendar.ts","../src/svg/icons/check.ts","../src/svg/icons/chevronDown.ts","../src/svg/icons/chevronLeft.ts","../src/svg/icons/chevronRight.ts","../src/svg/icons/chevronUp.ts","../src/svg/icons/circle.ts","../src/svg/icons/copy.ts","../src/svg/icons/download.ts","../src/svg/icons/edit.ts","../src/svg/icons/externalLink.ts","../src/svg/icons/eye.ts","../src/svg/icons/eyeOff.ts","../src/svg/icons/filter.ts","../src/svg/icons/heart.ts","../src/svg/icons/home.ts","../src/svg/icons/info.ts","../src/svg/icons/link.ts","../src/svg/icons/loader.ts","../src/svg/icons/lock.ts","../src/svg/icons/mail.ts","../src/svg/icons/menu.ts","../src/svg/icons/minus.ts","../src/svg/icons/moon.ts","../src/svg/icons/moreHorizontal.ts","../src/svg/icons/phone.ts","../src/svg/icons/plus.ts","../src/svg/icons/refreshCw.ts","../src/svg/icons/search.ts","../src/svg/icons/settings.ts","../src/svg/icons/star.ts","../src/svg/icons/sun.ts","../src/svg/icons/trash.ts","../src/svg/icons/upload.ts","../src/svg/icons/user.ts","../src/svg/icons/x.ts","../src/svg/icons/index.ts","../src/core/classNames.ts","../src/core/styleInjector.ts","../src/components/avatar/Avatar.ts","../src/components/badge/Badge.ts","../src/components/button/Button.ts","../src/components/button/ButtonGroup.ts","../src/components/checkbox/Checkbox.ts","../src/core/overlay.ts","../src/components/command/Command.ts","../src/components/data/List.ts","../src/components/data/Table.ts","../src/components/data/Tree.ts","../src/components/feedback/Alert.ts","../src/components/feedback/ProgressBar.ts","../src/components/feedback/Skeleton.ts","../src/components/feedback/Spinner.ts","../src/components/feedback/Toast.ts","../src/components/field/shared.ts","../src/components/field/ColorField.ts","../src/components/field/textInput.css.ts","../src/components/field/NumberField.ts","../src/components/field/TextArea.ts","../src/components/field/TextField.ts","../src/core/content.ts","../src/components/hovercard/HoverCard.ts","../src/components/input/ChipInput.ts","../src/components/select/Combobox.ts","../src/components/input/DatePicker.ts","../src/components/input/FileDropzone.ts","../src/components/layout/Card.ts","../src/components/layout/Section.ts","../src/components/layout/Separator.ts","../src/components/misc/ModeCard.ts","../src/components/navigation/Accordion.ts","../src/components/navigation/Breadcrumb.ts","../src/components/navigation/Pagination.ts","../src/components/navigation/Tabs.ts","../src/components/overlay/Dialog.ts","../src/components/overlay/AlertDialog.ts","../src/components/overlay/DropdownMenu.ts","../src/components/overlay/ContextMenu.ts","../src/components/overlay/Drawer.ts","../src/components/overlay/Popover.ts","../src/components/radio/RadioGroup.ts","../src/components/select/Select.ts","../src/components/slider/Slider.ts","../src/components/slider/RangeSlider.ts","../src/components/switch/Switch.ts","../src/components/toggle/Toggle.ts","../src/components/toggle/ToggleGroup.ts","../src/components/tooltip/Tooltip.ts"],"sourcesContent":["/**\r\n * True when running in an environment with a real `document`/`window`\r\n * (browser, or Node/Bun with a DOM shim like `happy-dom`/`linkedom`).\r\n */\r\nexport function isBrowser(): boolean {\r\n return typeof document !== 'undefined' && typeof window !== 'undefined'\r\n}\r\n\r\n/**\r\n * Guards a component factory against being called without a DOM, throwing\r\n * one clear, actionable error instead of a cryptic `ReferenceError`.\r\n *\r\n * @param componentName - Name shown in the thrown error, e.g. `'Button'`.\r\n */\r\nexport function assertDom(componentName: string): void {\r\n if (!isBrowser()) throw new Error(`[linteau] \"${componentName}\" requires a DOM environment (a browser, or Node/Bun with a DOM shim such as 'happy-dom' or 'linkedom'). No 'document' was found.`)\r\n}\r\n\r\n/** Tiny `document.createElement` wrapper that also applies an initial class name. */\r\nexport function el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\r\n const node = document.createElement(tag)\r\n if (className) node.className = className\r\n return node\r\n}","/** A listener function subscribed to a single event of type `T`. */\r\nexport type Listener<T> = (payload: T) => void\r\n\r\n/** A minimal, fully-typed event emitter used internally by stateful components. */\r\nexport interface Emitter<TEvents extends Record<string, unknown>> {\r\n /** Subscribes to an event, returning an unsubscribe function. */\r\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void\r\n /** Removes a previously-subscribed listener. */\r\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void\r\n /** Synchronously notifies every listener subscribed to `event`. */\r\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void\r\n /** Removes every listener for every event. */\r\n clear: () => void\r\n}\r\n\r\n/** Creates a standalone, strongly-typed event emitter. */\r\nexport function createEmitter<TEvents extends Record<string, unknown>>(): Emitter<TEvents> {\r\n const listeners = new Map<keyof TEvents, Set<Listener<any>>>()\r\n return {\r\n on(event, listener) {\r\n if (!listeners.has(event)) listeners.set(event, new Set())\r\n listeners.get(event)!.add(listener)\r\n return () => listeners.get(event)?.delete(listener)\r\n },\r\n off(event, listener) {\r\n listeners.get(event)?.delete(listener)\r\n },\r\n emit(event, payload) {\r\n listeners.get(event)?.forEach((listener) => listener(payload))\r\n },\r\n clear() {\r\n listeners.clear()\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Merges a strongly-typed controller API onto a real DOM element, producing\r\n * a single value that IS a valid Node (append it anywhere) AND a fully\r\n * controllable component instance (no wrapper object required).\r\n *\r\n * This is the pattern every Linteau component factory returns through.\r\n *\r\n * @typeParam TElement - The native element type being extended, e.g. `HTMLButtonElement`.\r\n * @typeParam TApi - The extra methods/properties to attach.\r\n * @param element - The native element instance created by the component.\r\n * @param api - The controller methods/properties to merge onto the element.\r\n * @returns The same element instance, typed as `TElement & TApi`.\r\n */\r\nexport function attachController<TElement extends HTMLElement, TApi extends object>(element: TElement, api: TApi): TElement & TApi {\r\n return Object.assign(element, api)\r\n}\r\n\r\n/** A small helper for collecting and running teardown callbacks in `destroy()` implementations. */\r\nexport function createCleanup(): { add: (fn: () => void) => void, run: () => void } {\r\n const fns: Array<() => void> = []\r\n return {\r\n add(fn) {\r\n fns.push(fn)\r\n },\r\n run() {\r\n while (fns.length > 0) fns.pop()?.()\r\n }\r\n }\r\n}","/** Every design token Linteau exposes as a `--linteau-*` CSS custom property. */\r\nexport interface LinteauThemeTokens {\r\n background: string\r\n foreground: string\r\n card: string\r\n cardForeground: string\r\n primary: string\r\n primaryForeground: string\r\n secondary: string\r\n secondaryForeground: string\r\n muted: string\r\n mutedForeground: string\r\n accent: string\r\n accentForeground: string\r\n destructive: string\r\n destructiveForeground: string\r\n success: string\r\n successForeground: string\r\n warning: string\r\n warningForeground: string\r\n border: string\r\n input: string\r\n ring: string\r\n radius: string\r\n radiusSm: string\r\n radiusMd: string\r\n radiusLg: string\r\n radiusXl: string\r\n}\r\n\r\n/** Linteau's built-in dark theme -- the same OKLCH palette used across every component. */\r\nexport const defaultTheme: LinteauThemeTokens = {\r\n background: 'oklch(0.09 0 0)',\r\n foreground: 'oklch(0.94 0 0)',\r\n card: 'oklch(0.12 0 0)',\r\n cardForeground: 'oklch(0.94 0 0)',\r\n primary: 'oklch(0.92 0 0)',\r\n primaryForeground: 'oklch(0.1 0 0)',\r\n secondary: 'oklch(0.18 0 0)',\r\n secondaryForeground: 'oklch(0.9 0 0)',\r\n muted: 'oklch(0.16 0 0)',\r\n mutedForeground: 'oklch(0.6 0 0)',\r\n accent: 'oklch(0.2 0 0)',\r\n accentForeground: 'oklch(0.94 0 0)',\r\n destructive: 'oklch(0.58 0.22 27)',\r\n destructiveForeground: 'oklch(0.97 0 0)',\r\n success: 'oklch(0.62 0.16 145)',\r\n successForeground: 'oklch(0.97 0 0)',\r\n warning: 'oklch(0.75 0.15 85)',\r\n warningForeground: 'oklch(0.15 0 0)',\r\n border: 'oklch(0.22 0 0)',\r\n input: 'oklch(0.22 0 0)',\r\n ring: 'oklch(0.7 0 0)',\r\n radius: '0.625rem',\r\n radiusSm: 'calc(0.625rem - 4px)',\r\n radiusMd: 'calc(0.625rem - 2px)',\r\n radiusLg: '0.625rem',\r\n radiusXl: 'calc(0.625rem + 4px)'\r\n}\r\n\r\n/** Builds the `:root { --linteau-*: ...; }` stylesheet text for a given set of theme tokens. */\r\nexport function buildTokensCss(tokens: LinteauThemeTokens): string {\r\n return `:root {\r\n --linteau-background: ${tokens.background};\r\n --linteau-foreground: ${tokens.foreground};\r\n --linteau-card: ${tokens.card};\r\n --linteau-card-foreground: ${tokens.cardForeground};\r\n --linteau-primary: ${tokens.primary};\r\n --linteau-primary-foreground: ${tokens.primaryForeground};\r\n --linteau-secondary: ${tokens.secondary};\r\n --linteau-secondary-foreground: ${tokens.secondaryForeground};\r\n --linteau-muted: ${tokens.muted};\r\n --linteau-muted-foreground: ${tokens.mutedForeground};\r\n --linteau-accent: ${tokens.accent};\r\n --linteau-accent-foreground: ${tokens.accentForeground};\r\n --linteau-destructive: ${tokens.destructive};\r\n --linteau-destructive-foreground: ${tokens.destructiveForeground};\r\n --linteau-success: ${tokens.success};\r\n --linteau-success-foreground: ${tokens.successForeground};\r\n --linteau-warning: ${tokens.warning};\r\n --linteau-warning-foreground: ${tokens.warningForeground};\r\n --linteau-border: ${tokens.border};\r\n --linteau-input: ${tokens.input};\r\n --linteau-ring: ${tokens.ring};\r\n --linteau-radius: ${tokens.radius};\r\n --linteau-radius-sm: ${tokens.radiusSm};\r\n --linteau-radius-md: ${tokens.radiusMd};\r\n --linteau-radius-lg: ${tokens.radiusLg};\r\n --linteau-radius-xl: ${tokens.radiusXl};\r\n}`\r\n}","import { isBrowser } from './dom'\r\nimport { createEmitter } from './controller'\r\nimport { buildTokensCss, defaultTheme } from '../styles/tokens'\r\nimport type { LinteauThemeTokens } from '../styles/tokens'\r\n\r\nconst TOKENS_STYLE_ID = 'linteau-tokens'\r\n\r\nlet currentTheme: LinteauThemeTokens = { ...defaultTheme }\r\nconst emitter = createEmitter<{ change: Readonly<LinteauThemeTokens> }>()\r\n\r\nfunction applyThemeToDom(): void {\r\n if (!isBrowser()) return\r\n let style = document.getElementById(TOKENS_STYLE_ID) as HTMLStyleElement | null\r\n if (!style) {\r\n style = document.createElement('style')\r\n style.id = TOKENS_STYLE_ID\r\n document.head.appendChild(style)\r\n }\r\n style.textContent = buildTokensCss(currentTheme)\r\n}\r\n\r\n/** Returns the currently active theme tokens (read-only snapshot). */\r\nexport function getTheme(): Readonly<LinteauThemeTokens> {\r\n return currentTheme\r\n}\r\n\r\n/**\r\n * Overrides one or more theme tokens at runtime. Any token you omit keeps\r\n * its current value. Re-injects the `:root { --linteau-* }` style tag and\r\n * notifies subscribers registered via `onThemeChange`.\r\n *\r\n * @param overrides - Partial theme tokens to merge over the current theme.\r\n */\r\nexport function setTheme(overrides: Partial<LinteauThemeTokens>): void {\r\n currentTheme = { ...currentTheme, ...overrides }\r\n applyThemeToDom()\r\n emitter.emit('change', currentTheme)\r\n}\r\n\r\n/** Restores every theme token to Linteau's built-in defaults. */\r\nexport function resetTheme(): void {\r\n currentTheme = { ...defaultTheme }\r\n applyThemeToDom()\r\n emitter.emit('change', currentTheme)\r\n}\r\n\r\n/**\r\n * Subscribes to theme changes made via `setTheme`/`resetTheme`.\r\n * @returns An unsubscribe function.\r\n */\r\nexport function onThemeChange(listener: (theme: Readonly<LinteauThemeTokens>) => void): () => void {\r\n return emitter.on('change', listener)\r\n}\r\n\r\n// Safe at module load: `applyThemeToDom` checks `isBrowser()` first, so this\r\n// is a guaranteed no-op in Node/Bun and an automatic style injection in the browser.\r\napplyThemeToDom()","import type { IconInput, IconRenderProps, IconShape } from './types'\r\n\r\nconst SVGNS = 'http://www.w3.org/2000/svg'\r\n\r\n/** Builds the shared base attributes (sizing, stroke, viewBox) applied to every rendered icon `<svg>`. */\r\nfunction baseAttrs(props: IconRenderProps): Record<string, string> {\r\n const size = String(props.size ?? 16)\r\n return {\r\n xmlns: SVGNS,\r\n width: size,\r\n height: size,\r\n viewBox: '0 0 24 24',\r\n fill: 'none',\r\n stroke: props.color ?? 'currentColor',\r\n 'stroke-width': String(props.strokeWidth ?? 2),\r\n 'stroke-linecap': 'round',\r\n 'stroke-linejoin': 'round'\r\n }\r\n}\r\n\r\n/**\r\n * Renders a static `IconShape` into a real `SVGSVGElement`.\r\n *\r\n * Exported so per-icon components (`svg/icons/*`) can reuse the exact same rendering\r\n * path as the generic `Icon()` dispatcher below -- one source of truth, no duplication.\r\n */\r\nexport function renderIconShape(shape: IconShape, props: IconRenderProps): SVGSVGElement {\r\n const svg = document.createElementNS(SVGNS, 'svg') as SVGSVGElement\r\n const attrs = baseAttrs(props)\r\n for (const key in attrs) svg.setAttribute(key, attrs[key] as string)\r\n if (props.className) svg.setAttribute('class', props.className)\r\n for (const [tag, childAttrs] of shape) {\r\n const node = document.createElementNS(SVGNS, tag)\r\n for (const key in childAttrs) node.setAttribute(key, childAttrs[key] as string)\r\n svg.appendChild(node)\r\n }\r\n return svg\r\n}\r\n\r\n/** Clones an existing `SVGSVGElement`, re-applying size/color/stroke/class overrides. */\r\nfunction fromElement(source: SVGSVGElement, props: IconRenderProps): SVGSVGElement {\r\n const svg = source.cloneNode(true) as SVGSVGElement\r\n const size = String(props.size ?? 16)\r\n svg.setAttribute('width', size)\r\n svg.setAttribute('height', size)\r\n if (props.color) svg.setAttribute('stroke', props.color)\r\n if (props.strokeWidth != null) svg.setAttribute('stroke-width', String(props.strokeWidth))\r\n if (props.className) svg.classList.add(...props.className.split(' ').filter(Boolean))\r\n return svg\r\n}\r\n\r\n/** Parses raw `<svg>...</svg>` markup into a real element before delegating to `fromElement`. */\r\nfunction fromMarkup(markup: string, props: IconRenderProps): SVGSVGElement {\r\n const doc = new DOMParser().parseFromString(markup, 'image/svg+xml')\r\n return fromElement(doc.documentElement as unknown as SVGSVGElement, props)\r\n}\r\n\r\n/**\r\n * Renders any supported `IconInput` shape into a real `SVGSVGElement`.\r\n * Returns `null` when input is `null`/`undefined`, so callers never need to branch\r\n * before rendering an optional icon.\r\n *\r\n * @param input - The icon source: shape array, raw markup, an existing element, a component/render function, or nothing.\r\n * @param size - Shorthand for `props.size` (overridden if `props.size` is also set).\r\n * @param props - Additional render props: color, strokeWidth, className.\r\n * @requires A DOM environment (browser, or Node/Bun with a DOM shim).\r\n */\r\nexport function Icon(input: IconInput, size?: number | string, props: IconRenderProps = {}): SVGSVGElement | null {\r\n if (input === null || input === undefined) return null\r\n const resolved: IconRenderProps = { ...(size !== undefined ? { size } : {}), ...props }\r\n if (typeof input === 'function') return input(resolved)\r\n if (typeof input === 'string') return fromMarkup(input, resolved)\r\n if (input instanceof SVGElement) return fromElement(input as SVGSVGElement, resolved)\r\n if (Array.isArray(input)) return renderIconShape(input, resolved)\r\n return null\r\n}","import { renderIconShape } from './Icon'\r\nimport type { IconComponent, IconRenderProps, IconShape } from './types'\r\n\r\n/**\r\n * Builds a ready-to-use icon component from a static shape -- mirroring how lucide\r\n * generates one component per icon via `createLucideIcon`.\r\n *\r\n * Every file in `svg/icons/*` calls this once and exports the result, so each icon\r\n * is a real, standalone, tree-shakeable SVG component instead of a shared data blob.\r\n *\r\n * @param name - Icon name, stamped onto the rendered element as `data-icon` (debugging/theming hook).\r\n * @param shape - The ordered list of child nodes that make up the icon.\r\n * @returns A component: call it with optional render props to get a fresh `SVGSVGElement`.\r\n */\r\nexport function createIcon(name: string, shape: IconShape): IconComponent {\r\n return function renderIcon(props: IconRenderProps = {}): SVGSVGElement {\r\n const svg = renderIconShape(shape, props)\r\n svg.setAttribute('data-icon', name)\r\n return svg\r\n }\r\n}","import { createIcon } from '../create-icon'\r\n\r\nexport const alertTriangle = createIcon('alert-triangle', [\r\n ['path', { d: 'M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z' }],\r\n ['line', { x1: '12', y1: '9', x2: '12', y2: '13' }],\r\n ['line', { x1: '12', y1: '17', x2: '12.01', y2: '17' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const bell = createIcon('bell', [\r\n ['path', { d: 'M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9' }],\r\n ['path', { d: 'M10.3 21a1.94 1.94 0 0 0 3.4 0' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const calendar = createIcon('calendar', [\r\n ['rect', { x: '3', y: '4', width: '18', height: '18', rx: '2' }],\r\n ['line', { x1: '16', y1: '2', x2: '16', y2: '6' }],\r\n ['line', { x1: '8', y1: '2', x2: '8', y2: '6' }],\r\n ['line', { x1: '3', y1: '10', x2: '21', y2: '10' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const check = createIcon('check', [\r\n ['polyline', { points: '20 6 9 17 4 12' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const chevronDown = createIcon('chevron-down', [\r\n ['polyline', { points: '6 9 12 15 18 9' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const chevronLeft = createIcon('chevron-left', [\r\n ['polyline', { points: '15 18 9 12 15 6' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const chevronRight = createIcon('chevron-right', [\r\n ['polyline', { points: '9 18 15 12 9 6' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const chevronUp = createIcon('chevron-up', [\r\n ['polyline', { points: '18 15 12 9 6 15' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const circle = createIcon('circle', [\r\n ['circle', { cx: '12', cy: '12', r: '10' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const copy = createIcon('copy', [\r\n ['rect', { width: '14', height: '14', x: '8', y: '8', rx: '2', ry: '2' }],\r\n ['path', { d: 'M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const download = createIcon('download', [\r\n ['path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' }],\r\n ['polyline', { points: '7 10 12 15 17 10' }],\r\n ['line', { x1: '12', y1: '15', x2: '12', y2: '3' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const edit = createIcon('edit', [\r\n ['path', { d: 'M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const externalLink = createIcon('external-link', [\r\n ['path', { d: 'M15 3h6v6' }],\r\n ['path', { d: 'M10 14 21 3' }],\r\n ['path', { d: 'M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const eye = createIcon('eye', [\r\n ['path', { d: 'M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z' }],\r\n ['circle', { cx: '12', cy: '12', r: '3' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const eyeOff = createIcon('eye-off', [\r\n ['path', { d: 'M9.88 9.88a3 3 0 1 0 4.24 4.24' }],\r\n ['path', { d: 'M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68' }],\r\n ['path', { d: 'M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61' }],\r\n ['line', { x1: '2', y1: '2', x2: '22', y2: '22' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const filter = createIcon('filter', [\r\n ['polygon', { points: '22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const heart = createIcon('heart', [\r\n ['path', { d: 'M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const home = createIcon('home', [\r\n ['path', { d: 'M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' }],\r\n ['polyline', { points: '9 22 9 12 15 12 15 22' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const info = createIcon('info', [\r\n ['circle', { cx: '12', cy: '12', r: '10' }],\r\n ['line', { x1: '12', y1: '16', x2: '12', y2: '12' }],\r\n ['line', { x1: '12', y1: '8', x2: '12.01', y2: '8' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const link = createIcon('link', [\r\n ['path', { d: 'M9 17H7A5 5 0 0 1 7 7h2' }],\r\n ['path', { d: 'M15 7h2a5 5 0 1 1 0 10h-2' }],\r\n ['line', { x1: '8', y1: '12', x2: '16', y2: '12' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const loader = createIcon('loader', [\r\n ['line', { x1: '12', y1: '2', x2: '12', y2: '6' }],\r\n ['line', { x1: '12', y1: '18', x2: '12', y2: '22' }],\r\n ['line', { x1: '4.9', y1: '4.9', x2: '7.8', y2: '7.8' }],\r\n ['line', { x1: '16.2', y1: '16.2', x2: '19.1', y2: '19.1' }],\r\n ['line', { x1: '2', y1: '12', x2: '6', y2: '12' }],\r\n ['line', { x1: '18', y1: '12', x2: '22', y2: '12' }],\r\n ['line', { x1: '4.9', y1: '19.1', x2: '7.8', y2: '16.2' }],\r\n ['line', { x1: '16.2', y1: '7.8', x2: '19.1', y2: '4.9' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const lock = createIcon('lock', [\r\n ['rect', { x: '3', y: '11', width: '18', height: '11', rx: '2', ry: '2' }],\r\n ['path', { d: 'M7 11V7a5 5 0 0 1 10 0v4' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const mail = createIcon('mail', [\r\n ['rect', { width: '20', height: '16', x: '2', y: '4', rx: '2' }],\r\n ['path', { d: 'm22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const menu = createIcon('menu', [\r\n ['line', { x1: '4', y1: '12', x2: '20', y2: '12' }],\r\n ['line', { x1: '4', y1: '6', x2: '20', y2: '6' }],\r\n ['line', { x1: '4', y1: '18', x2: '20', y2: '18' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const minus = createIcon('minus', [\r\n ['line', { x1: '5', y1: '12', x2: '19', y2: '12' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const moon = createIcon('moon', [\r\n ['path', { d: 'M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const moreHorizontal = createIcon('more-horizontal', [\r\n ['circle', { cx: '5', cy: '12', r: '1' }],\r\n ['circle', { cx: '12', cy: '12', r: '1' }],\r\n ['circle', { cx: '19', cy: '12', r: '1' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const phone = createIcon('phone', [\r\n ['path', { d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const plus = createIcon('plus', [\r\n ['line', { x1: '12', y1: '5', x2: '12', y2: '19' }],\r\n ['line', { x1: '5', y1: '12', x2: '19', y2: '12' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const refreshCw = createIcon('refresh-cw', [\r\n ['path', { d: 'M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8' }],\r\n ['path', { d: 'M3 3v5h5' }],\r\n ['path', { d: 'M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16' }],\r\n ['path', { d: 'M16 16h5v5' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const search = createIcon('search', [\r\n ['circle', { cx: '11', cy: '11', r: '8' }],\r\n ['line', { x1: '21', y1: '21', x2: '16.65', y2: '16.65' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const settings = createIcon('settings', [\r\n ['path', { d: 'M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z' }],\r\n ['circle', { cx: '12', cy: '12', r: '3' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const star = createIcon('star', [\r\n ['polygon', { points: '12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const sun = createIcon('sun', [\r\n ['circle', { cx: '12', cy: '12', r: '4' }],\r\n ['line', { x1: '12', y1: '2', x2: '12', y2: '4' }],\r\n ['line', { x1: '12', y1: '20', x2: '12', y2: '22' }],\r\n ['line', { x1: '4.93', y1: '4.93', x2: '6.34', y2: '6.34' }],\r\n ['line', { x1: '17.66', y1: '17.66', x2: '19.07', y2: '19.07' }],\r\n ['line', { x1: '2', y1: '12', x2: '4', y2: '12' }],\r\n ['line', { x1: '20', y1: '12', x2: '22', y2: '12' }],\r\n ['line', { x1: '6.34', y1: '17.66', x2: '4.93', y2: '19.07' }],\r\n ['line', { x1: '19.07', y1: '4.93', x2: '17.66', y2: '6.34' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const trash = createIcon('trash', [\r\n ['path', { d: 'M3 6h18' }],\r\n ['path', { d: 'M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2' }],\r\n ['path', { d: 'M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6' }],\r\n ['line', { x1: '10', y1: '11', x2: '10', y2: '17' }],\r\n ['line', { x1: '14', y1: '11', x2: '14', y2: '17' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const upload = createIcon('upload', [\r\n ['path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' }],\r\n ['polyline', { points: '17 8 12 3 7 8' }],\r\n ['line', { x1: '12', y1: '3', x2: '12', y2: '15' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const user = createIcon('user', [\r\n ['path', { d: 'M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2' }],\r\n ['circle', { cx: '12', cy: '7', r: '4' }]\r\n])","import { createIcon } from '../create-icon'\r\n\r\nexport const x = createIcon('x', [\r\n ['line', { x1: '18', y1: '6', x2: '6', y2: '18' }],\r\n ['line', { x1: '6', y1: '6', x2: '18', y2: '18' }]\r\n])","import { alertTriangle } from './alertTriangle'\nimport { bell } from './bell'\nimport { calendar } from './calendar'\nimport { check } from './check'\nimport { chevronDown } from './chevronDown'\nimport { chevronLeft } from './chevronLeft'\nimport { chevronRight } from './chevronRight'\nimport { chevronUp } from './chevronUp'\nimport { circle } from './circle'\nimport { copy } from './copy'\nimport { download } from './download'\nimport { edit } from './edit'\nimport { externalLink } from './externalLink'\nimport { eye } from './eye'\nimport { eyeOff } from './eyeOff'\nimport { filter } from './filter'\nimport { heart } from './heart'\nimport { home } from './home'\nimport { info } from './info'\nimport { link } from './link'\nimport { loader } from './loader'\nimport { lock } from './lock'\nimport { mail } from './mail'\nimport { menu } from './menu'\nimport { minus } from './minus'\nimport { moon } from './moon'\nimport { moreHorizontal } from './moreHorizontal'\nimport { phone } from './phone'\nimport { plus } from './plus'\nimport { refreshCw } from './refreshCw'\nimport { search } from './search'\nimport { settings } from './settings'\nimport { star } from './star'\nimport { sun } from './sun'\nimport { trash } from './trash'\nimport { upload } from './upload'\nimport { user } from './user'\nimport { x } from './x'\nimport type { IconComponent } from '../types'\n\nexport { alertTriangle } from './alertTriangle'\nexport { bell } from './bell'\nexport { calendar } from './calendar'\nexport { check } from './check'\nexport { chevronDown } from './chevronDown'\nexport { chevronLeft } from './chevronLeft'\nexport { chevronRight } from './chevronRight'\nexport { chevronUp } from './chevronUp'\nexport { circle } from './circle'\nexport { copy } from './copy'\nexport { download } from './download'\nexport { edit } from './edit'\nexport { externalLink } from './externalLink'\nexport { eye } from './eye'\nexport { eyeOff } from './eyeOff'\nexport { filter } from './filter'\nexport { heart } from './heart'\nexport { home } from './home'\nexport { info } from './info'\nexport { link } from './link'\nexport { loader } from './loader'\nexport { lock } from './lock'\nexport { mail } from './mail'\nexport { menu } from './menu'\nexport { minus } from './minus'\nexport { moon } from './moon'\nexport { moreHorizontal } from './moreHorizontal'\nexport { phone } from './phone'\nexport { plus } from './plus'\nexport { refreshCw } from './refreshCw'\nexport { search } from './search'\nexport { settings } from './settings'\nexport { star } from './star'\nexport { sun } from './sun'\nexport { trash } from './trash'\nexport { upload } from './upload'\nexport { user } from './user'\nexport { x } from './x'\n\n/**\n * Linteau's built-in icon set, keyed by name -- auto-generated by `scripts/generate-icons.ts`\n * from every file in `svg/icons/*`. Do not edit this file by hand: add or remove an icon\n * file instead and re-run `bun run generate:icons` (any `build`/`typecheck`/`serve` run\n * does this automatically for you).\n *\n * Every entry is a real, standalone `IconComponent`, so this object is fully interchangeable\n * with, and spreadable alongside, your own lucide clone:\n *\n * ```ts\n * import { icons } from 'linteau/svg'\n * const allIcons: Record<string, IconComponent> = { ...icons, ...myLucideCloneIcons }\n * ```\n */\nexport const icons: Record<string, IconComponent> = {\n alertTriangle,\n bell,\n calendar,\n check,\n chevronDown,\n chevronLeft,\n chevronRight,\n chevronUp,\n circle,\n copy,\n download,\n edit,\n externalLink,\n eye,\n eyeOff,\n filter,\n heart,\n home,\n info,\n link,\n loader,\n lock,\n mail,\n menu,\n minus,\n moon,\n moreHorizontal,\n phone,\n plus,\n refreshCw,\n search,\n settings,\n star,\n sun,\n trash,\n upload,\n user,\n x\n}\n","/** Every class name Linteau generates starts with this prefix, so it can never collide with a consumer's own CSS. */\r\nexport const PREFIX = 'linteau-' as const\r\n\r\n/** Prefixes a class-name fragment with the library namespace, e.g. `px('button')` -> `'linteau-button'`. */\r\nexport function px(part: string): string {\r\n return `${PREFIX}${part}`\r\n}\r\n\r\n/** Joins class-name fragments, dropping any falsy value. Handy for conditional classes. */\r\nexport function cx(...parts: Array<string | false | null | undefined>): string {\r\n return parts.filter(Boolean).join(' ')\r\n}","import { isBrowser } from './dom'\r\n\r\nconst STYLE_ID = 'linteau-styles'\r\nconst injectedKeys = new Set<string>()\r\n\r\n/** A handful of utility classes nearly every component depends on (icon color, hidden state). Injected once, ahead of any component-specific CSS. */\r\nconst baseCss = `\r\n.linteau-hidden { display: none !important }\r\n.linteau-icon { color: var(--linteau-muted-foreground); flex-shrink: 0 }\r\n`\r\n\r\nfunction getStyleSheet(): HTMLStyleElement | null {\r\n if (!isBrowser) return null\r\n let sheet = document.getElementById(STYLE_ID) as HTMLStyleElement | null\r\n if (!sheet) {\r\n sheet = document.createElement('style')\r\n sheet.id = STYLE_ID\r\n document.head.appendChild(sheet)\r\n }\r\n return sheet\r\n}\r\n\r\n/**\r\n * Injects a single CSS block exactly once, keyed by `key`. Safe to call from every\r\n * instance of every component -- the second and later calls for the same key are no-ops.\r\n *\r\n * Each component factory calls this with its own colocated CSS string right after\r\n * `assertDom`, so consumers never import or link any CSS file themselves -- and an app\r\n * that only imports `Button` never pays for `Dialog`'s or `Table`'s styles.\r\n *\r\n * @param key - A stable identifier for this CSS block (typically the component name). Shared blocks (e.g. field-base) reuse the same key across multiple components to dedupe.\r\n * @param css - The raw CSS text to inject.\r\n */\r\nexport function ensureComponentStyles(key: string, css: string): void {\r\n const sheet = getStyleSheet()\r\n if (!sheet) return\r\n if (!injectedKeys.has('base')) {\r\n sheet.appendChild(document.createTextNode(baseCss))\r\n injectedKeys.add('base')\r\n }\r\n if (injectedKeys.has(key)) return\r\n sheet.appendChild(document.createTextNode(css))\r\n injectedKeys.add(key)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** Options accepted by the `Avatar` factory. */\r\nexport interface AvatarOptions {\r\n /** Image URL. Falls back to `initials` if omitted or if the image fails to load. */\r\n src?: string\r\n /** Accessible alt text for the image. */\r\n alt?: string\r\n /** Fallback text (typically 1-2 letters) shown when there's no image. */\r\n initials?: string\r\n /** Pixel diameter/side length. Defaults to `36`. */\r\n size?: number\r\n /** Outline shape. Defaults to `'circle'`. */\r\n shape?: 'circle' | 'square'\r\n}\r\n\r\n/** The runtime control surface attached to every `Avatar` element. */\r\nexport interface AvatarApi {\r\n /** Replaces the image source, or falls back to initials if `undefined`. */\r\n setSrc: (src: string | undefined) => void\r\n /** Detaches the avatar from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** An `Avatar` is a real `HTMLDivElement` extended with `AvatarApi`. */\r\nexport type AvatarElement = HTMLDivElement & AvatarApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const avatarCss = `\r\n.linteau-avatar { display: inline-flex; align-items: center; justify-content: center; background: var(--linteau-secondary); color: var(--linteau-secondary-foreground); font-size: 12px; font-weight: 600; overflow: hidden; flex-shrink: 0 }\r\n.linteau-avatar-circle { border-radius: 50% }\r\n.linteau-avatar-square { border-radius: var(--linteau-radius-sm) }\r\n.linteau-avatar img { width: 100%; height: 100%; object-fit: cover }\r\n`\r\n\r\n/** Creates a circular or square avatar with an automatic initials fallback. */\r\nexport function Avatar(options: AvatarOptions = {}): AvatarElement {\r\n assertDom('Avatar')\r\n ensureComponentStyles('avatar', avatarCss)\r\n const size = options.size ?? 36\r\n const shape = options.shape ?? 'circle'\r\n const root = el('div', cx(px('avatar'), px(`avatar-${shape}`)))\r\n root.style.width = `${size}px`\r\n root.style.height = `${size}px`\r\n function render(src: string | undefined): void {\r\n root.replaceChildren()\r\n if (src) {\r\n const img = document.createElement('img')\r\n img.src = src\r\n img.alt = options.alt ?? ''\r\n img.addEventListener('error', () => render(undefined), { once: true })\r\n root.appendChild(img)\r\n } else {\r\n const fallback = document.createElement('span')\r\n fallback.textContent = options.initials ?? ''\r\n root.appendChild(fallback)\r\n }\r\n }\r\n render(options.src)\r\n const api: AvatarApi = {\r\n setSrc(src) {\r\n render(src)\r\n },\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Visual style of a `Badge`. */\r\nexport type BadgeVariant = 'default' | 'outline' | 'success' | 'warning' | 'destructive'\r\n\r\n/** Options accepted by the `Badge` factory. */\r\nexport interface BadgeOptions {\r\n /** Visual style. Defaults to `'default'`. */\r\n variant?: BadgeVariant\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n}\r\n\r\n/** The runtime control surface attached to every `Badge` element. */\r\nexport interface BadgeApi {\r\n /** Updates the visible label text. */\r\n setLabel: (text: string) => void\r\n /** Swaps the visual variant, updating classes in place. */\r\n setVariant: (variant: BadgeVariant) => void\r\n /** Detaches the badge from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Badge` is a real `HTMLSpanElement` extended with `BadgeApi`. */\r\nexport type BadgeElement = HTMLSpanElement & BadgeApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const badgeCss = `\r\n.linteau-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 2px 8px;\r\n border-radius: 999px;\r\n font-size: 11px;\r\n font-weight: 600;\r\n line-height: 1.6;\r\n border: 1px solid transparent;\r\n}\r\n.linteau-badge-default { background: var(--linteau-secondary); color: var(--linteau-secondary-foreground) }\r\n.linteau-badge-outline { background: transparent; border-color: var(--linteau-border); color: var(--linteau-foreground) }\r\n.linteau-badge-success { background: var(--linteau-success); color: var(--linteau-success-foreground) }\r\n.linteau-badge-warning { background: var(--linteau-warning); color: var(--linteau-warning-foreground) }\r\n.linteau-badge-destructive { background: var(--linteau-destructive); color: var(--linteau-destructive-foreground) }\r\n`\r\n\r\n/** Creates a small pill-shaped status/label indicator. */\r\nexport function Badge(text: string, options: BadgeOptions = {}): BadgeElement {\r\n assertDom('Badge')\r\n ensureComponentStyles('badge', badgeCss)\r\n let variant = options.variant ?? 'default'\r\n const span = el('span', cx(px('badge'), px(`badge-${variant}`)))\r\n const label = document.createElement('span')\r\n label.textContent = text\r\n if (options.icon) span.appendChild(Icon(options.icon, 11, { className: px('icon') })!)\r\n span.appendChild(label)\r\n const api: BadgeApi = {\r\n setLabel(newText) {\r\n label.textContent = newText\r\n },\r\n setVariant(newVariant) {\r\n span.classList.remove(px(`badge-${variant}`))\r\n variant = newVariant\r\n span.classList.add(px(`badge-${variant}`))\r\n },\r\n destroy() {\r\n span.remove()\r\n }\r\n }\r\n return attachController(span, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Visual style of a `Button`. */\r\nexport type ButtonVariant = 'default' | 'outline' | 'ghost' | 'destructive'\r\n/** Sizing preset of a `Button`. */\r\nexport type ButtonSize = 'sm' | 'default'\r\n\r\n/** Options accepted by the `Button` factory. */\r\nexport interface ButtonOptions {\r\n /** Visual style. Defaults to `'default'`. */\r\n variant?: ButtonVariant\r\n /** Sizing preset. Defaults to `'default'`. */\r\n size?: ButtonSize\r\n /** Optional icon, in any `IconInput` shape. */\r\n icon?: IconInput\r\n /** Which side of the label the icon renders on. Defaults to `'start'`. */\r\n iconPosition?: 'start' | 'end'\r\n /** Disables the button and blocks click handling. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Stretches the button to 100% of its container's width. Defaults to `false`. */\r\n fullWidth?: boolean\r\n /** Called on every click while the button is enabled. */\r\n onClick?: (event: MouseEvent) => void\r\n}\r\n\r\n/** The full runtime control surface attached to every `Button` element. */\r\nexport interface ButtonApi {\r\n /** Updates the visible label text. */\r\n setLabel: (text: string) => void\r\n /** Swaps the visual variant, updating classes in place. */\r\n setVariant: (variant: ButtonVariant) => void\r\n /** Swaps the sizing preset, updating classes in place. */\r\n setSize: (size: ButtonSize) => void\r\n /** Replaces the icon (or removes it if `icon` is `null`/`undefined`), optionally moving its position. */\r\n setIcon: (icon: IconInput, position?: 'start' | 'end') => void\r\n /** Enables/disables the button. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Replaces the click handler (pass `undefined` to remove it). */\r\n setOnClick: (handler: ((event: MouseEvent) => void) | undefined) => void\r\n /** Removes the click listener and detaches the button from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Button` is a real `HTMLButtonElement` extended with `ButtonApi`. */\r\nexport type ButtonElement = HTMLButtonElement & ButtonApi\r\n\r\n/** This component's own CSS -- colocated so `Button.ts` is a single, self-contained, tree-shakeable unit. */\r\nexport const buttonCss = `\r\n.linteau-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n border-radius: var(--linteau-radius-sm);\r\n border: 1px solid transparent;\r\n font-size: 13px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: background 120ms ease, border-color 120ms ease, transform 120ms ease, opacity 120ms ease;\r\n}\r\n.linteau-button-default { padding: 10px 14px }\r\n.linteau-button-sm { padding: 6px 10px; font-size: 12px }\r\n.linteau-button-full { width: 100% }\r\n.linteau-button:active { transform: scale(0.97) }\r\n.linteau-button:disabled { opacity: 0.5; cursor: not-allowed; transform: none }\r\n.linteau-button-default:not(.linteau-button-outline):not(.linteau-button-ghost):not(.linteau-button-destructive) {\r\n background: var(--linteau-primary);\r\n color: var(--linteau-primary-foreground);\r\n}\r\n.linteau-button-default:not(.linteau-button-outline):not(.linteau-button-ghost):not(.linteau-button-destructive):hover:not(:disabled) {\r\n filter: brightness(0.92);\r\n}\r\n.linteau-button-outline { background: transparent; border-color: var(--linteau-border); color: var(--linteau-foreground) }\r\n.linteau-button-outline:hover:not(:disabled) { background: var(--linteau-accent) }\r\n.linteau-button-ghost { background: transparent; color: var(--linteau-muted-foreground) }\r\n.linteau-button-ghost:hover:not(:disabled) { background: var(--linteau-accent); color: var(--linteau-foreground) }\r\n.linteau-button-destructive { background: var(--linteau-destructive); color: var(--linteau-destructive-foreground) }\r\n.linteau-button-destructive:hover:not(:disabled) { filter: brightness(0.92) }\r\n`\r\n\r\n/**\r\n * Creates a fully controllable, self-styled button.\r\n *\r\n * @param text - Initial label text.\r\n * @param options - Configuration; every field is optional and can change later via the returned API.\r\n * @returns The button element itself, extended with `ButtonApi` methods.\r\n */\r\nexport function Button(text: string, options: ButtonOptions = {}): ButtonElement {\r\n assertDom('Button')\r\n ensureComponentStyles('button', buttonCss)\r\n let { variant = 'default', size = 'default' } = options\r\n let { icon, iconPosition = 'start', disabled = false } = options\r\n let onClickHandler = options.onClick\r\n const button = el('button', cx(px('button'), px(`button-${variant}`), px(`button-${size}`), options.fullWidth && px('button-full')))\r\n button.type = 'button'\r\n button.disabled = disabled\r\n const label = document.createElement('span')\r\n label.className = px('button-label')\r\n label.textContent = text\r\n function render(): void {\r\n button.replaceChildren()\r\n const iconEl = icon ? Icon(icon, 14, { className: px('icon') }) : null\r\n const nodes: Node[] = []\r\n if (iconEl && iconPosition === 'start') nodes.push(iconEl)\r\n nodes.push(label)\r\n if (iconEl && iconPosition === 'end') nodes.push(iconEl)\r\n button.append(...nodes)\r\n }\r\n render()\r\n const listener = (event: MouseEvent): void => { if (!disabled) onClickHandler?.(event) }\r\n button.addEventListener('click', listener)\r\n const api: ButtonApi = {\r\n setLabel(newText) {\r\n label.textContent = newText\r\n },\r\n setVariant(newVariant) {\r\n button.classList.remove(px(`button-${variant}`))\r\n variant = newVariant\r\n button.classList.add(px(`button-${variant}`))\r\n },\r\n setSize(newSize) {\r\n button.classList.remove(px(`button-${size}`))\r\n size = newSize\r\n button.classList.add(px(`button-${size}`))\r\n },\r\n setIcon(newIcon, position) {\r\n icon = newIcon\r\n if (position) iconPosition = position\r\n render()\r\n },\r\n setDisabled(value) {\r\n disabled = value\r\n button.disabled = value\r\n },\r\n setOnClick(handler) {\r\n onClickHandler = handler\r\n },\r\n destroy() {\r\n button.removeEventListener('click', listener)\r\n button.remove()\r\n }\r\n }\r\n return attachController(button, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Button } from './Button'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single selectable item within a `ButtonGroup`. */\r\nexport interface ButtonGroupItem {\r\n /** Visible label. */\r\n label: string\r\n /** Unique value identifying this item. */\r\n value: string\r\n /** Optional icon shown before the label. */\r\n icon?: IconInput\r\n}\r\n\r\n/** Options accepted by the `ButtonGroup` factory. */\r\nexport interface ButtonGroupOptions {\r\n /** The items rendered as segments. */\r\n items: ButtonGroupItem[]\r\n /** Initially selected value (controlled if you keep calling `setValue`, uncontrolled otherwise). */\r\n value?: string\r\n /** Called whenever the selection changes via user interaction. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `ButtonGroup` element. */\r\nexport interface ButtonGroupApi {\r\n /** Returns the currently selected value, if any. */\r\n getValue: () => string | undefined\r\n /** Programmatically selects a value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Replaces the full list of items, preserving selection where possible. */\r\n setItems: (items: ButtonGroupItem[]) => void\r\n /** Detaches the group from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ButtonGroup` is a real `HTMLDivElement` extended with `ButtonGroupApi`. */\r\nexport type ButtonGroupElement = HTMLDivElement & ButtonGroupApi\r\n\r\n/** This component's own CSS. Depends on `.linteau-button`, which `Button()` registers itself the moment `ButtonGroup` renders its first segment. */\r\nexport const buttonGroupCss = `\r\n.linteau-button-group { display: inline-flex; border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-sm); overflow: hidden }\r\n.linteau-button-group .linteau-button { border-radius: 0; border: none; border-right: 1px solid var(--linteau-border); background: transparent; color: var(--linteau-muted-foreground) }\r\n.linteau-button-group .linteau-button:last-child { border-right: none }\r\n.linteau-button-group .linteau-button:hover:not(:disabled) { background: var(--linteau-accent) }\r\n.linteau-button-group .linteau-button-group-item-active { background: var(--linteau-primary); color: var(--linteau-primary-foreground) }\r\n`\r\n\r\n/** Creates a segmented, single-select group of buttons -- useful for compact mode/tab-like pickers that don't need a full `Select`. */\r\nexport function ButtonGroup(options: ButtonGroupOptions): ButtonGroupElement {\r\n assertDom('ButtonGroup')\r\n ensureComponentStyles('button-group', buttonGroupCss)\r\n let items = options.items\r\n let value = options.value\r\n const onChange = options.onChange\r\n const root = el('div', px('button-group'))\r\n root.setAttribute('role', 'group')\r\n function render(): void {\r\n root.replaceChildren()\r\n for (const item of items) {\r\n const isActive = item.value === value\r\n const button = Button(item.label, {\r\n icon: item.icon,\r\n variant: 'ghost',\r\n onClick: () => {\r\n value = item.value\r\n render()\r\n onChange?.(item.value)\r\n }\r\n })\r\n button.classList.toggle(px('button-group-item-active'), isActive)\r\n root.appendChild(button)\r\n }\r\n }\r\n render()\r\n const api: ButtonGroupApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n render()\r\n },\r\n setItems(newItems) {\r\n items = newItems\r\n render()\r\n },\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Options accepted by the `Checkbox` factory. */\r\nexport interface CheckboxOptions {\r\n /** Label rendered next to the box. */\r\n label: string\r\n /** Controlled checked state. */\r\n checked?: boolean\r\n /** Uncontrolled initial state, used only if `checked` is omitted. Defaults to `false`. */\r\n defaultChecked?: boolean\r\n /** Renders a dash instead of a check mark, without affecting the boolean value. Defaults to `false`. */\r\n indeterminate?: boolean\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user toggles the checkbox. */\r\n onChange?: (checked: boolean) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Checkbox` element. */\r\nexport interface CheckboxApi {\r\n /** Returns the current checked state. */\r\n getValue: () => boolean\r\n /** Programmatically sets the checked state (does not trigger `onChange`). */\r\n setValue: (checked: boolean) => void\r\n /** Toggles the indeterminate visual state. */\r\n setIndeterminate: (indeterminate: boolean) => void\r\n /** Enables/disables the checkbox. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the checkbox from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Checkbox` is a real `HTMLDivElement` (the row) extended with `CheckboxApi`. */\r\nexport type CheckboxElement = HTMLDivElement & CheckboxApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const checkboxCss = `\r\n.linteau-checkbox-row { display: flex; align-items: center; gap: 8px }\r\n.linteau-checkbox {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: var(--linteau-radius-sm);\r\n border: 1px solid var(--linteau-border);\r\n background: var(--linteau-secondary);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n color: var(--linteau-primary-foreground);\r\n}\r\n.linteau-checkbox:disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-checkbox.linteau-checked { background: var(--linteau-primary); border-color: var(--linteau-primary) }\r\n.linteau-checkbox svg { display: none }\r\n.linteau-checkbox.linteau-checked svg, .linteau-checkbox.linteau-indeterminate svg { display: block }\r\n`\r\n\r\n/** Creates a labeled checkbox, supporting controlled/uncontrolled and indeterminate states. */\r\nexport function Checkbox(options: CheckboxOptions): CheckboxElement {\r\n assertDom('Checkbox')\r\n ensureComponentStyles('checkbox', checkboxCss)\r\n let checked = options.checked ?? options.defaultChecked ?? false\r\n let indeterminate = options.indeterminate ?? false\r\n let disabled = options.disabled ?? false\r\n const onChange = options.onChange\r\n const root = el('div', px('checkbox-row'))\r\n const box = el('button', px('checkbox'))\r\n box.type = 'button'\r\n box.setAttribute('role', 'checkbox')\r\n box.disabled = disabled\r\n const checkIcon = Icon(icons.check, 12)!\r\n const dashIcon = Icon(icons.minus, 12)!\r\n box.append(checkIcon, dashIcon)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n function render(): void {\r\n box.classList.toggle(px('checked'), checked)\r\n box.classList.toggle(px('indeterminate'), indeterminate && !checked)\r\n box.setAttribute('aria-checked', indeterminate ? 'mixed' : String(checked))\r\n checkIcon.style.display = checked ? 'block' : 'none'\r\n dashIcon.style.display = !checked && indeterminate ? 'block' : 'none'\r\n }\r\n render()\r\n const listener = (): void => {\r\n if (disabled) return\r\n checked = !checked\r\n indeterminate = false\r\n render()\r\n onChange?.(checked)\r\n }\r\n box.addEventListener('click', listener)\r\n root.append(box, labelText)\r\n const api: CheckboxApi = {\r\n getValue() {\r\n return checked\r\n },\r\n setValue(value) {\r\n checked = value\r\n indeterminate = false\r\n render()\r\n },\r\n setIndeterminate(value) {\r\n indeterminate = value\r\n render()\r\n },\r\n setDisabled(value) {\r\n disabled = value\r\n box.disabled = value\r\n },\r\n destroy() {\r\n box.removeEventListener('click', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { isBrowser } from './dom'\r\n\r\n/** Placement of a floating element relative to its anchor. */\r\nexport type FloatingPlacement = 'top' | 'bottom' | 'left' | 'right'\r\n\r\n/**\r\n * Calls `callback` when a mouse press lands outside every element in `targets`.\r\n * Accepts one or more elements so a floating panel and its anchor can both be excluded.\r\n * @returns An unsubscribe function.\r\n */\r\nexport function onClickOutside(targets: HTMLElement | HTMLElement[], callback: () => void): () => void {\r\n if (!isBrowser()) return () => { }\r\n const list = Array.isArray(targets) ? targets : [targets]\r\n const listener = (event: MouseEvent): void => {\r\n const node = event.target as Node\r\n if (list.some((target) => target.contains(node))) return\r\n callback()\r\n }\r\n document.addEventListener('mousedown', listener, true)\r\n return () => document.removeEventListener('mousedown', listener, true)\r\n}\r\n\r\n/** Calls `callback` whenever the Escape key is pressed. @returns An unsubscribe function. */\r\nexport function onEscapeKey(callback: () => void): () => void {\r\n if (!isBrowser()) return () => { }\r\n const listener = (event: KeyboardEvent): void => { if (event.key === 'Escape') callback() }\r\n document.addEventListener('keydown', listener)\r\n return () => document.removeEventListener('keydown', listener)\r\n}\r\n\r\n/** Locks page scroll (used by modal-like overlays). @returns A function that restores the previous overflow value. */\r\nexport function lockBodyScroll(): () => void {\r\n if (!isBrowser()) return () => { }\r\n const previous = document.body.style.overflow\r\n document.body.style.overflow = 'hidden'\r\n return () => { document.body.style.overflow = previous }\r\n}\r\n\r\n/** Positions `floating` next to `anchor`, clamped to stay inside the viewport. */\r\nexport function positionFloating(anchor: HTMLElement, floating: HTMLElement, placement: FloatingPlacement = 'bottom', gap = 6): void {\r\n if (!isBrowser()) return\r\n const anchorRect = anchor.getBoundingClientRect()\r\n const floatingRect = floating.getBoundingClientRect()\r\n let top = 0\r\n let left = 0\r\n if (placement === 'bottom') {\r\n top = anchorRect.bottom + gap\r\n left = anchorRect.left\r\n } else if (placement === 'top') {\r\n top = anchorRect.top - floatingRect.height - gap\r\n left = anchorRect.left\r\n } else if (placement === 'left') {\r\n top = anchorRect.top\r\n left = anchorRect.left - floatingRect.width - gap\r\n } else {\r\n top = anchorRect.top\r\n left = anchorRect.right + gap\r\n }\r\n const maxLeft = window.innerWidth - floatingRect.width - 8\r\n const maxTop = window.innerHeight - floatingRect.height - 8\r\n floating.style.position = 'fixed'\r\n floating.style.top = `${Math.max(8, Math.min(top, maxTop))}px`\r\n floating.style.left = `${Math.max(8, Math.min(left, maxLeft))}px`\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onEscapeKey, lockBodyScroll } from '../../core/overlay'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single selectable entry in a `Command` palette. */\r\nexport interface CommandItem {\r\n /** Visible label. */\r\n label: string\r\n /** Value passed to `onSelect` when this item is chosen. */\r\n value: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Extra terms matched against the search query, alongside `label`. */\r\n keywords?: string[]\r\n /** Disables this item. Defaults to `false`. */\r\n disabled?: boolean\r\n}\r\n\r\n/** A labeled cluster of `CommandItem`s within the palette. */\r\nexport interface CommandGroup {\r\n /** Optional heading shown above this group's items. */\r\n heading?: string\r\n /** The items in this group. */\r\n items: CommandItem[]\r\n}\r\n\r\n/** Options accepted by the `Command` factory. */\r\nexport interface CommandOptions {\r\n /** The groups of selectable items. */\r\n groups?: CommandGroup[]\r\n /** Placeholder shown in the search input. Defaults to `'Type a command or search...'`. */\r\n placeholder?: string\r\n /** Text shown when no items match the query. Defaults to `'No results found.'`. */\r\n emptyText?: string\r\n /** Closes the palette after a selection is made. Defaults to `true`. */\r\n closeOnSelect?: boolean\r\n /** Called when an enabled item is chosen. */\r\n onSelect?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Command` element. */\r\nexport interface CommandApi {\r\n /** Opens the palette, locks scroll, and focuses the search input. */\r\n open: () => void\r\n /** Closes the palette. */\r\n close: () => void\r\n /** Toggles between open and closed. */\r\n toggle: () => void\r\n /** Returns whether the palette is currently open. */\r\n isOpen: () => boolean\r\n /** Replaces the full list of groups. */\r\n setGroups: (groups: CommandGroup[]) => void\r\n /** Removes all listeners and detaches the palette from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Command` is a real `HTMLDivElement` (the overlay) extended with `CommandApi`. */\r\nexport type CommandElement = HTMLDivElement & CommandApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const commandCss = `\r\n.linteau-command-overlay { position: fixed; inset: 0; background: color-mix(in oklch, black 60%, transparent); display: flex; align-items: flex-start; justify-content: center; padding-top: 15vh; z-index: 1500; backdrop-filter: blur(4px) }\r\n.linteau-command-panel { width: min(560px, 92vw); max-height: 60vh; display: flex; flex-direction: column; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); overflow: hidden }\r\n.linteau-command-input-wrap { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--linteau-border) }\r\n.linteau-command-input { flex: 1; background: transparent; border: none; outline: none; color: var(--linteau-foreground); font-size: 14px; font-family: inherit }\r\n.linteau-command-list { overflow-y: auto; padding: 6px; flex: 1 }\r\n.linteau-command-group-heading { padding: 6px 8px 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--linteau-muted-foreground) }\r\n.linteau-command-item { display: flex; align-items: center; gap: 8px; padding: 8px; border-radius: var(--linteau-radius-sm); font-size: 13px; color: var(--linteau-foreground); cursor: pointer }\r\n.linteau-command-item-highlighted { background: var(--linteau-accent) }\r\n.linteau-command-item-disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-command-empty { padding: 24px; text-align: center; font-size: 12px; color: var(--linteau-muted-foreground) }\r\n`\r\n\r\n/**\r\n * Creates a full-screen command palette: a search input backed by a live-filtered,\r\n * grouped, keyboard-navigable list -- opened on demand (bind it to a keyboard shortcut\r\n * like Cmd/Ctrl+K in your app).\r\n */\r\nexport function Command(options: CommandOptions = {}): CommandElement {\r\n assertDom('Command')\r\n ensureComponentStyles('command', commandCss)\r\n let groups = options.groups ?? []\r\n const closeOnSelect = options.closeOnSelect ?? true\r\n const onSelect = options.onSelect\r\n let query = ''\r\n let highlighted = 0\r\n let isOpen = false\r\n let unlockScroll: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const overlay = el('div', cx(px('command-overlay'), px('hidden')))\r\n const panel = el('div', px('command-panel'))\r\n panel.setAttribute('role', 'dialog')\r\n panel.setAttribute('aria-modal', 'true')\r\n const inputWrap = el('div', px('command-input-wrap'))\r\n const searchIcon = Icon(icons.search, 14, { className: px('icon') })\r\n if (searchIcon) inputWrap.appendChild(searchIcon)\r\n const input = el('input', px('command-input'))\r\n input.type = 'text'\r\n input.placeholder = options.placeholder ?? 'Type a command or search...'\r\n inputWrap.appendChild(input)\r\n const list = el('div', px('command-list'))\r\n panel.append(inputWrap, list)\r\n overlay.appendChild(panel)\r\n\r\n function filteredFlat(): CommandItem[] {\r\n const normalized = query.trim().toLowerCase()\r\n const all = groups.flatMap((group) => group.items)\r\n if (!normalized) return all\r\n return all.filter((item) => item.label.toLowerCase().includes(normalized) || item.keywords?.some((k) => k.toLowerCase().includes(normalized)))\r\n }\r\n\r\n function renderList(): void {\r\n list.replaceChildren()\r\n const normalized = query.trim().toLowerCase()\r\n const flat = filteredFlat()\r\n if (flat.length === 0) {\r\n const empty = el('div', px('command-empty'))\r\n empty.textContent = options.emptyText ?? 'No results found.'\r\n list.appendChild(empty)\r\n return\r\n }\r\n let runningIndex = 0\r\n for (const group of groups) {\r\n const matchingItems = group.items.filter((item) => !normalized || item.label.toLowerCase().includes(normalized) || item.keywords?.some((k) => k.toLowerCase().includes(normalized)))\r\n if (matchingItems.length === 0) continue\r\n if (group.heading) {\r\n const heading = el('div', px('command-group-heading'))\r\n heading.textContent = group.heading\r\n list.appendChild(heading)\r\n }\r\n for (const item of matchingItems) {\r\n const index = runningIndex++\r\n const itemEl = el('div', cx(px('command-item'), index === highlighted && px('command-item-highlighted'), item.disabled && px('command-item-disabled')))\r\n if (item.icon) itemEl.appendChild(Icon(item.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = item.label\r\n itemEl.appendChild(label)\r\n itemEl.addEventListener('mousedown', (event) => {\r\n event.preventDefault()\r\n selectItem(item)\r\n })\r\n itemEl.addEventListener('mouseenter', () => {\r\n highlighted = index\r\n renderList()\r\n })\r\n list.appendChild(itemEl)\r\n }\r\n }\r\n }\r\n\r\n function selectItem(item: CommandItem): void {\r\n if (item.disabled) return\r\n onSelect?.(item.value)\r\n if (closeOnSelect) close()\r\n }\r\n\r\n function handleKeydown(event: KeyboardEvent): void {\r\n const flat = filteredFlat()\r\n if (event.key === 'ArrowDown') {\r\n event.preventDefault()\r\n highlighted = Math.min(highlighted + 1, flat.length - 1)\r\n renderList()\r\n } else if (event.key === 'ArrowUp') {\r\n event.preventDefault()\r\n highlighted = Math.max(highlighted - 1, 0)\r\n renderList()\r\n } else if (event.key === 'Enter') {\r\n event.preventDefault()\r\n const item = flat[highlighted]\r\n if (item) selectItem(item)\r\n }\r\n }\r\n\r\n const inputListener = (): void => {\r\n query = input.value\r\n highlighted = 0\r\n renderList()\r\n }\r\n input.addEventListener('input', inputListener)\r\n input.addEventListener('keydown', handleKeydown)\r\n const backdropListener = (event: MouseEvent): void => {\r\n if (event.target === overlay) close()\r\n }\r\n overlay.addEventListener('mousedown', backdropListener)\r\n\r\n function open(): void {\r\n if (isOpen) return\r\n isOpen = true\r\n query = ''\r\n highlighted = 0\r\n input.value = ''\r\n overlay.classList.remove(px('hidden'))\r\n renderList()\r\n unlockScroll = lockBodyScroll()\r\n unbindEscape = onEscapeKey(close)\r\n input.focus()\r\n }\r\n function close(): void {\r\n if (!isOpen) return\r\n isOpen = false\r\n overlay.classList.add(px('hidden'))\r\n unlockScroll?.()\r\n unlockScroll = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n function toggle(): void {\r\n if (isOpen) close()\r\n else open()\r\n }\r\n const api: CommandApi = {\r\n open,\r\n close,\r\n toggle,\r\n isOpen() {\r\n return isOpen\r\n },\r\n setGroups(newGroups) {\r\n groups = newGroups\r\n renderList()\r\n },\r\n destroy() {\r\n input.removeEventListener('input', inputListener)\r\n input.removeEventListener('keydown', handleKeydown)\r\n overlay.removeEventListener('mousedown', backdropListener)\r\n unlockScroll?.()\r\n unbindEscape?.()\r\n overlay.remove()\r\n }\r\n }\r\n return attachController(overlay, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single row rendered inside a `List`. */\r\nexport interface ListItem {\r\n /** Visible label. */\r\n label: string\r\n /** Unique value identifying this row. */\r\n value: string\r\n /** Optional icon rendered before the text. */\r\n icon?: IconInput\r\n /** Optional secondary line under the label. */\r\n description?: string\r\n}\r\n\r\n/** Options accepted by the `List` factory. */\r\nexport interface ListOptions {\r\n /** The rows to render. */\r\n items: ListItem[]\r\n /** Enables single-select highlighting/interaction. Defaults to `true`. */\r\n selectable?: boolean\r\n /** Controlled selected value. */\r\n value?: string\r\n /** Called whenever the user selects a row (only when `selectable`). */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `List` element. */\r\nexport interface ListApi {\r\n /** Returns the currently selected value, if any. */\r\n getValue: () => string | undefined\r\n /** Programmatically selects a value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Replaces the full list of rows. */\r\n setItems: (items: ListItem[]) => void\r\n /** Detaches the list from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `List` is a real `HTMLDivElement` extended with `ListApi`. */\r\nexport type ListElement = HTMLDivElement & ListApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const listCss = `\r\n.linteau-list { display: flex; flex-direction: column; gap: 2px; width: 100% }\r\n.linteau-list-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--linteau-radius-sm); cursor: pointer }\r\n.linteau-list-item:hover { background: var(--linteau-accent) }\r\n.linteau-list-item-selected { background: var(--linteau-accent) }\r\n.linteau-list-item-text { display: flex; flex-direction: column }\r\n.linteau-list-item-label { font-size: 13px; color: var(--linteau-foreground) }\r\n.linteau-list-item-description { font-size: 11px; color: var(--linteau-muted-foreground) }\r\n`\r\n\r\n/** Creates a vertical list of rows, optionally single-selectable. */\r\nexport function List(options: ListOptions): ListElement {\r\n assertDom('List')\r\n ensureComponentStyles('list', listCss)\r\n let items = options.items\r\n const selectable = options.selectable ?? true\r\n let value = options.value\r\n const onChange = options.onChange\r\n const cleanupListeners: Array<() => void> = []\r\n const root = el('div', px('list'))\r\n function render(): void {\r\n root.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n for (const item of items) {\r\n const row = el('div', cx(px('list-item'), selectable && item.value === value && px('list-item-selected')))\r\n if (item.icon) row.appendChild(Icon(item.icon, 16, { className: px('icon') })!)\r\n const textWrap = el('div', px('list-item-text'))\r\n const label = el('div', px('list-item-label'))\r\n label.textContent = item.label\r\n textWrap.appendChild(label)\r\n if (item.description) {\r\n const description = el('div', px('list-item-description'))\r\n description.textContent = item.description\r\n textWrap.appendChild(description)\r\n }\r\n row.appendChild(textWrap)\r\n if (selectable) {\r\n const listener = (): void => {\r\n value = item.value\r\n render()\r\n onChange?.(item.value)\r\n }\r\n row.addEventListener('click', listener)\r\n cleanupListeners.push(() => row.removeEventListener('click', listener))\r\n }\r\n root.appendChild(row)\r\n }\r\n }\r\n render()\r\n const api: ListApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n render()\r\n },\r\n setItems(newItems) {\r\n items = newItems\r\n render()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Sort direction used by `Table`. */\r\nexport type SortDirection = 'asc' | 'desc'\r\n\r\n/** Definition of a single `Table` column. */\r\nexport interface TableColumn<TRow> {\r\n /** Unique key, also used as the sort key passed to `onSortChange`. */\r\n key: string\r\n /** Header label. */\r\n header: string\r\n /** Allows this column's header to trigger sorting. Defaults to `false`. */\r\n sortable?: boolean\r\n /** Custom cell renderer; defaults to reading `row[key]` as a string if omitted. */\r\n render?: (row: TRow) => HTMLElement | string\r\n}\r\n\r\n/** Options accepted by the `Table` factory. */\r\nexport interface TableOptions<TRow> {\r\n /** Column definitions, in display order. */\r\n columns: Array<TableColumn<TRow>>\r\n /** The rows to render. */\r\n rows: TRow[]\r\n /** Derives a stable string id for a row; used only internally for key stability. */\r\n getRowId?: (row: TRow) => string\r\n /** Called when the user clicks a sortable header. */\r\n onSortChange?: (key: string, direction: SortDirection) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Table` element. */\r\nexport interface TableApi<TRow> {\r\n /** Replaces the rows shown, re-rendering the body. */\r\n setRows: (rows: TRow[]) => void\r\n /** Detaches the table from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Table` is a real `HTMLDivElement` (the scroll wrapper) extended with `TableApi`. */\r\nexport type TableElement<TRow> = HTMLDivElement & TableApi<TRow>\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const tableCss = `\r\n.linteau-table-wrap { width: 100%; overflow-x: auto; border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg) }\r\n.linteau-table { width: 100%; border-collapse: collapse; font-size: 12px }\r\n.linteau-table th { text-align: left; padding: 10px 12px; background: var(--linteau-muted); color: var(--linteau-muted-foreground); font-weight: 600; border-bottom: 1px solid var(--linteau-border); cursor: default; white-space: nowrap }\r\n.linteau-table th.linteau-table-sortable { cursor: pointer; user-select: none }\r\n.linteau-table td { padding: 10px 12px; border-bottom: 1px solid var(--linteau-border); color: var(--linteau-foreground) }\r\n.linteau-table tr:last-child td { border-bottom: none }\r\n.linteau-table-sort-icon { display: inline-block; margin-left: 4px; vertical-align: middle }\r\n`\r\n\r\n/** Creates a data table with optional click-to-sort headers and custom cell rendering. */\r\nexport function Table<TRow>(options: TableOptions<TRow>): TableElement<TRow> {\r\n assertDom('Table')\r\n ensureComponentStyles('table', tableCss)\r\n let rows = options.rows\r\n let sortKey: string | null = null\r\n let sortDirection: SortDirection = 'asc'\r\n const cleanupListeners: Array<() => void> = []\r\n const wrap = el('div', px('table-wrap'))\r\n const table = el('table', px('table'))\r\n const thead = document.createElement('thead')\r\n const tbody = document.createElement('tbody')\r\n function renderHead(): void {\r\n thead.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n const headRow = document.createElement('tr')\r\n for (const column of options.columns) {\r\n const th = document.createElement('th')\r\n th.className = cx(px('table-sortable-cell'), column.sortable && px('table-sortable'))\r\n th.textContent = column.header\r\n if (column.sortable) {\r\n if (sortKey === column.key) {\r\n const sortIcon = Icon(sortDirection === 'asc' ? icons.chevronUp : icons.chevronDown, 12, { className: px('table-sort-icon') })\r\n if (sortIcon) th.appendChild(sortIcon)\r\n }\r\n const listener = (): void => {\r\n sortDirection = sortKey === column.key && sortDirection === 'asc' ? 'desc' : 'asc'\r\n sortKey = column.key\r\n renderHead()\r\n options.onSortChange?.(column.key, sortDirection)\r\n }\r\n th.addEventListener('click', listener)\r\n cleanupListeners.push(() => th.removeEventListener('click', listener))\r\n }\r\n headRow.appendChild(th)\r\n }\r\n thead.appendChild(headRow)\r\n }\r\n function renderBody(): void {\r\n tbody.replaceChildren()\r\n for (const row of rows) {\r\n const tr = document.createElement('tr')\r\n for (const column of options.columns) {\r\n const td = document.createElement('td')\r\n const content = column.render ? column.render(row) : String((row as Record<string, unknown>)[column.key] ?? '')\r\n if (content instanceof HTMLElement) td.appendChild(content)\r\n else td.textContent = content\r\n tr.appendChild(td)\r\n }\r\n tbody.appendChild(tr)\r\n }\r\n }\r\n renderHead()\r\n renderBody()\r\n table.append(thead, tbody)\r\n wrap.appendChild(table)\r\n const api: TableApi<TRow> = {\r\n setRows(newRows) {\r\n rows = newRows\r\n renderBody()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n wrap.remove()\r\n }\r\n }\r\n return attachController(wrap, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single node in a `Tree`, optionally containing children. */\r\nexport interface TreeNode {\r\n /** Visible label. */\r\n label: string\r\n /** Unique value identifying this node. */\r\n value: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Nested child nodes. */\r\n children?: TreeNode[]\r\n}\r\n\r\n/** Options accepted by the `Tree` factory. */\r\nexport interface TreeOptions {\r\n /** The root-level nodes to render. */\r\n nodes: TreeNode[]\r\n /** Values expanded by default. */\r\n defaultExpanded?: string[]\r\n /** Called when a leaf or branch node is clicked. */\r\n onSelect?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Tree` element. */\r\nexport interface TreeApi {\r\n /** Expands every branch node. */\r\n expandAll: () => void\r\n /** Collapses every branch node. */\r\n collapseAll: () => void\r\n /** Detaches the tree from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Tree` is a real `HTMLDivElement` extended with `TreeApi`. */\r\nexport type TreeElement = HTMLDivElement & TreeApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const treeCss = `\r\n.linteau-tree { display: flex; flex-direction: column; gap: 2px }\r\n.linteau-tree-row { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: var(--linteau-radius-sm); cursor: pointer; font-size: 12px }\r\n.linteau-tree-row:hover { background: var(--linteau-accent) }\r\n.linteau-tree-chevron { transition: transform 150ms ease }\r\n.linteau-tree-chevron.linteau-open { transform: rotate(90deg) }\r\n.linteau-tree-children { margin-left: 18px; display: flex; flex-direction: column; gap: 2px }\r\n.linteau-tree-children.linteau-collapsed { display: none }\r\n`\r\n\r\n/** Creates a recursively nested, expandable tree of nodes. */\r\nexport function Tree(options: TreeOptions): TreeElement {\r\n assertDom('Tree')\r\n ensureComponentStyles('tree', treeCss)\r\n const expanded = new Set(options.defaultExpanded ?? [])\r\n const cleanupListeners: Array<() => void> = []\r\n const allValues: string[] = []\r\n const root = el('div', px('tree'))\r\n function collectValues(nodes: TreeNode[]): void {\r\n for (const node of nodes) {\r\n if (node.children?.length) {\r\n allValues.push(node.value)\r\n collectValues(node.children)\r\n }\r\n }\r\n }\r\n collectValues(options.nodes)\r\n function renderNode(node: TreeNode, container: HTMLElement): void {\r\n const hasChildren = Boolean(node.children?.length)\r\n const isOpen = expanded.has(node.value)\r\n const row = el('div', px('tree-row'))\r\n if (hasChildren) {\r\n const chevron = Icon(icons.chevronRight, 12, { className: cx(px('tree-chevron'), isOpen && px('open')) })\r\n if (chevron) row.appendChild(chevron)\r\n }\r\n if (node.icon) row.appendChild(Icon(node.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = node.label\r\n row.appendChild(label)\r\n const childrenContainer = hasChildren ? el('div', cx(px('tree-children'), !isOpen && px('collapsed'))) : null\r\n const listener = (): void => {\r\n if (hasChildren) {\r\n if (expanded.has(node.value)) expanded.delete(node.value)\r\n else expanded.add(node.value)\r\n render()\r\n }\r\n options.onSelect?.(node.value)\r\n }\r\n row.addEventListener('click', listener)\r\n cleanupListeners.push(() => row.removeEventListener('click', listener))\r\n container.appendChild(row)\r\n if (childrenContainer) {\r\n for (const child of node.children ?? []) renderNode(child, childrenContainer)\r\n container.appendChild(childrenContainer)\r\n }\r\n }\r\n function render(): void {\r\n root.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n for (const node of options.nodes) renderNode(node, root)\r\n }\r\n render()\r\n const api: TreeApi = {\r\n expandAll() {\r\n allValues.forEach((value) => expanded.add(value))\r\n render()\r\n },\r\n collapseAll() {\r\n expanded.clear()\r\n render()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Visual style of an `Alert`. */\r\nexport type AlertVariant = 'default' | 'success' | 'warning' | 'destructive'\r\n\r\n/** Options accepted by the `Alert` factory. */\r\nexport interface AlertOptions {\r\n /** Title shown above the description. */\r\n title?: string\r\n /** Visual style. Defaults to `'default'`. */\r\n variant?: AlertVariant\r\n /** Optional icon; defaults to a sensible one per variant if omitted. */\r\n icon?: IconInput\r\n /** Shows a close button. Defaults to `false`. */\r\n dismissible?: boolean\r\n /** Called when the close button is clicked. */\r\n onDismiss?: () => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Alert` element. */\r\nexport interface AlertApi {\r\n /** Updates the description text. */\r\n setDescription: (description: string) => void\r\n /** Detaches the alert from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** An `Alert` is a real `HTMLDivElement` extended with `AlertApi`. */\r\nexport type AlertElement = HTMLDivElement & AlertApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const alertCss = `\r\n.linteau-alert { display: flex; gap: 10px; padding: 12px; border-radius: var(--linteau-radius-lg); border: 1px solid var(--linteau-border); background: var(--linteau-muted) }\r\n.linteau-alert-success { border-color: var(--linteau-success) }\r\n.linteau-alert-warning { border-color: var(--linteau-warning) }\r\n.linteau-alert-destructive { border-color: var(--linteau-destructive) }\r\n.linteau-alert-body { flex: 1 }\r\n.linteau-alert-title { font-size: 13px; font-weight: 600; margin-bottom: 2px }\r\n.linteau-alert-description { font-size: 12px; color: var(--linteau-muted-foreground) }\r\n.linteau-alert-close { background: transparent; border: none; color: var(--linteau-muted-foreground); cursor: pointer; display: flex; align-self: flex-start }\r\n`\r\n\r\nconst defaultIconByVariant: Record<AlertVariant, IconInput> = {\r\n default: icons.info,\r\n success: icons.check,\r\n warning: icons.alertTriangle,\r\n destructive: icons.alertTriangle\r\n}\r\n\r\n/** Creates a static informational/status banner. */\r\nexport function Alert(description: string, options: AlertOptions = {}): AlertElement {\r\n assertDom('Alert')\r\n ensureComponentStyles('alert', alertCss)\r\n const variant = options.variant ?? 'default'\r\n const root = el('div', cx(px('alert'), px(`alert-${variant}`)))\r\n const iconEl = Icon(options.icon ?? defaultIconByVariant[variant], 18, { className: px('icon') })\r\n if (iconEl) root.appendChild(iconEl)\r\n const body = el('div', px('alert-body'))\r\n if (options.title) {\r\n const title = el('div', px('alert-title'))\r\n title.textContent = options.title\r\n body.appendChild(title)\r\n }\r\n const descriptionEl = el('div', px('alert-description'))\r\n descriptionEl.textContent = description\r\n body.appendChild(descriptionEl)\r\n root.appendChild(body)\r\n let closeListener: (() => void) | null = null\r\n if (options.dismissible) {\r\n const closeButton = el('button', px('alert-close'))\r\n closeButton.type = 'button'\r\n const closeIcon = Icon(icons.x, 14)\r\n if (closeIcon) closeButton.appendChild(closeIcon)\r\n closeListener = (): void => {\r\n options.onDismiss?.()\r\n root.remove()\r\n }\r\n closeButton.addEventListener('click', closeListener)\r\n root.appendChild(closeButton)\r\n }\r\n const api: AlertApi = {\r\n setDescription(description) {\r\n descriptionEl.textContent = description\r\n },\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** Options accepted by the `ProgressBar` factory. */\r\nexport interface ProgressBarOptions {\r\n /** Title shown at the top of the overlay card. */\r\n title?: string\r\n /** Initial progress percentage (0-100). Defaults to `0`. */\r\n value?: number\r\n /** Whether the bar starts in indeterminate (\"Working...\") mode. Defaults to `false`. */\r\n indeterminate?: boolean\r\n /** Whether the overlay is visible immediately. Defaults to `false`. */\r\n visible?: boolean\r\n}\r\n\r\n/** The runtime control surface attached to every `ProgressBar` element. */\r\nexport interface ProgressBarApi {\r\n /** Sets the progress percentage (clamped 0-100) and optional custom label text. */\r\n setValue: (percent: number, label?: string) => void\r\n /** Toggles indeterminate (\"Working...\") mode on or off. */\r\n setIndeterminate: (indeterminate: boolean) => void\r\n /** Updates the overlay title text. */\r\n setTitle: (title: string) => void\r\n /** Reveals the full-screen overlay. */\r\n show: () => void\r\n /** Hides the full-screen overlay. */\r\n hide: () => void\r\n /** Detaches the overlay from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ProgressBar` is a real `HTMLDivElement` extended with `ProgressBarApi`. */\r\nexport type ProgressBarElement = HTMLDivElement & ProgressBarApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const progressBarCss = `\r\n.linteau-progress-overlay { position: fixed; inset: 0; background: color-mix(in oklch, black 55%, transparent); display: flex; align-items: center; justify-content: center; z-index: 1000; backdrop-filter: blur(4px) }\r\n.linteau-progress-card { width: 280px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); padding: 20px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5) }\r\n.linteau-progress-title { font-size: 13px; font-weight: 600; margin-bottom: 12px; color: var(--linteau-foreground) }\r\n.linteau-progress-track { width: 100%; height: 8px; border-radius: 999px; background: var(--linteau-secondary); overflow: hidden; position: relative }\r\n.linteau-progress-fill { height: 100%; width: 0%; background: var(--linteau-primary); border-radius: 999px; transition: width 180ms ease }\r\n.linteau-progress-fill.linteau-indeterminate { width: 40% !important; animation: linteau-progress-slide 1.1s ease-in-out infinite }\r\n@keyframes linteau-progress-slide { 0% { transform: translateX(-100%) } 100% { transform: translateX(250%) } }\r\n.linteau-progress-percent { margin-top: 8px; font-size: 12px; color: var(--linteau-muted-foreground); text-align: right; font-variant-numeric: tabular-nums }\r\n`\r\n\r\n/** Creates a full-screen progress overlay, ideal for long-running async operations. */\r\nexport function ProgressBar(options: ProgressBarOptions = {}): ProgressBarElement {\r\n assertDom('ProgressBar')\r\n ensureComponentStyles('progress-bar', progressBarCss)\r\n const { title = '', value = 0, indeterminate = false, visible = false } = options\r\n const root = el('div', cx(px('progress-overlay'), !visible && px('hidden')))\r\n const card = el('div', px('progress-card'))\r\n const titleEl = el('div', px('progress-title'))\r\n titleEl.textContent = title\r\n const track = el('div', px('progress-track'))\r\n const fill = el('div', cx(px('progress-fill'), indeterminate && px('indeterminate')))\r\n track.appendChild(fill)\r\n const percentLabel = el('div', px('progress-percent'))\r\n percentLabel.textContent = indeterminate ? 'Working...' : `${Math.round(value)}%`\r\n card.append(titleEl, track, percentLabel)\r\n root.appendChild(card)\r\n fill.style.width = `${Math.max(0, Math.min(100, value))}%`\r\n const api: ProgressBarApi = {\r\n setValue(percent, label) {\r\n const clamped = Math.max(0, Math.min(100, percent))\r\n fill.classList.remove(px('indeterminate'))\r\n fill.style.width = `${clamped}%`\r\n percentLabel.textContent = label ?? `${Math.round(clamped)}%`\r\n },\r\n setIndeterminate(value) {\r\n fill.classList.toggle(px('indeterminate'), value)\r\n if (value) percentLabel.textContent = 'Working...'\r\n },\r\n setTitle(newTitle) {\r\n titleEl.textContent = newTitle\r\n },\r\n show() {\r\n root.classList.remove(px('hidden'))\r\n },\r\n hide() {\r\n root.classList.add(px('hidden'))\r\n },\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** Options accepted by the `Skeleton` factory. */\r\nexport interface SkeletonOptions {\r\n /** CSS width value or pixel number. Defaults to `'100%'`. */\r\n width?: string | number\r\n /** CSS height value or pixel number. Defaults to `'1em'`. */\r\n height?: string | number\r\n /** CSS border-radius value. Defaults to the theme's small radius. */\r\n radius?: string\r\n}\r\n\r\n/** The runtime control surface attached to every `Skeleton` element. */\r\nexport interface SkeletonApi {\r\n /** Detaches the placeholder from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Skeleton` is a real `HTMLDivElement` extended with `SkeletonApi`. */\r\nexport type SkeletonElement = HTMLDivElement & SkeletonApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const skeletonCss = `\r\n.linteau-skeleton { background: linear-gradient(90deg, var(--linteau-secondary) 25%, var(--linteau-accent) 37%, var(--linteau-secondary) 63%); background-size: 400% 100%; animation: linteau-skeleton-shine 1.4s ease infinite; border-radius: var(--linteau-radius-sm) }\r\n@keyframes linteau-skeleton-shine { 0% { background-position: 100% 50% } 100% { background-position: 0 50% } }\r\n`\r\n\r\n/** Creates an animated shimmering placeholder for content that's still loading. */\r\nexport function Skeleton(options: SkeletonOptions = {}): SkeletonElement {\r\n assertDom('Skeleton')\r\n ensureComponentStyles('skeleton', skeletonCss)\r\n const root = el('div', px('skeleton'))\r\n root.style.width = typeof options.width === 'number' ? `${options.width}px` : options.width ?? '100%'\r\n root.style.height = typeof options.height === 'number' ? `${options.height}px` : options.height ?? '1em'\r\n if (options.radius) root.style.borderRadius = options.radius\r\n const api: SkeletonApi = {\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Options accepted by the `Spinner` factory. */\r\nexport interface SpinnerOptions {\r\n /** Pixel size of the spinner. Defaults to `16`. */\r\n size?: number\r\n /** Stroke/text color. Defaults to `'currentColor'` via the icon's default. */\r\n color?: string\r\n}\r\n\r\n/** The runtime control surface attached to every `Spinner` element. */\r\nexport interface SpinnerApi {\r\n /** Resizes the spinner in place. */\r\n setSize: (size: number) => void\r\n /** Detaches the spinner from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Spinner` is a real `SVGSVGElement` extended with `SpinnerApi`. */\r\nexport type SpinnerElement = SVGSVGElement & SpinnerApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const spinnerCss = `\r\n.linteau-spinner { animation: linteau-spin 0.8s linear infinite; color: var(--linteau-muted-foreground) }\r\n@keyframes linteau-spin { to { transform: rotate(360deg) } }\r\n`\r\n\r\n/** Creates a small, continuously rotating loading indicator. */\r\nexport function Spinner(options: SpinnerOptions = {}): SpinnerElement {\r\n assertDom('Spinner')\r\n ensureComponentStyles('spinner', spinnerCss)\r\n const size = options.size ?? 16\r\n const svg = Icon(icons.loader, size, { className: px('spinner'), color: options.color })!\r\n const api: SpinnerApi = {\r\n setSize(newSize) {\r\n svg.setAttribute('width', String(newSize))\r\n svg.setAttribute('height', String(newSize))\r\n },\r\n destroy() {\r\n svg.remove()\r\n }\r\n }\r\n return attachController(svg as unknown as HTMLElement, api) as unknown as SpinnerElement\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Visual style of a `Toast`. */\r\nexport type ToastVariant = 'default' | 'success' | 'warning' | 'destructive'\r\n\r\n/** Options accepted by `ToastManager.show`. */\r\nexport interface ToastOptions {\r\n /** Toast title. */\r\n title?: string\r\n /** Supporting description text. */\r\n description?: string\r\n /** Visual style. Defaults to `'default'`. */\r\n variant?: ToastVariant\r\n /** Auto-dismiss delay in milliseconds. `0` disables auto-dismiss. Defaults to `4000`. */\r\n duration?: number\r\n}\r\n\r\n/** A stack-based toast notification manager. Lazily mounts its viewport to `document.body` on first use. */\r\nexport interface ToastManager {\r\n /** Shows a new toast and returns its id (usable with `dismiss`). */\r\n show: (options: ToastOptions) => string\r\n /** Dismisses a specific toast by id. */\r\n dismiss: (id: string) => void\r\n /** Dismisses every visible toast. */\r\n clear: () => void\r\n /** Removes the viewport entirely. */\r\n destroy: () => void\r\n}\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const toastCss = `\r\n.linteau-toast-viewport { position: fixed; bottom: 16px; right: 16px; display: flex; flex-direction: column; gap: 8px; z-index: 1400; width: min(340px, 92vw) }\r\n.linteau-toast { display: flex; gap: 8px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-left: 3px solid var(--linteau-primary); border-radius: var(--linteau-radius-md); padding: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) }\r\n.linteau-toast-success { border-left-color: var(--linteau-success) }\r\n.linteau-toast-warning { border-left-color: var(--linteau-warning) }\r\n.linteau-toast-destructive { border-left-color: var(--linteau-destructive) }\r\n.linteau-toast-body { flex: 1 }\r\n.linteau-toast-title { font-size: 12px; font-weight: 600 }\r\n.linteau-toast-description { font-size: 12px; color: var(--linteau-muted-foreground); margin-top: 2px }\r\n.linteau-toast-close { background: transparent; border: none; color: var(--linteau-muted-foreground); cursor: pointer; display: flex; align-self: flex-start }\r\n`\r\n\r\nlet idCounter = 0\r\n\r\n/** Creates an independent toast manager with its own viewport. Most apps only need the shared `toast` export below. */\r\nexport function createToastManager(): ToastManager {\r\n assertDom('ToastManager')\r\n ensureComponentStyles('toast', toastCss)\r\n let viewport: HTMLDivElement | null = null\r\n const timers = new Map<string, ReturnType<typeof setTimeout>>()\r\n function ensureViewport(): HTMLDivElement {\r\n if (!viewport) {\r\n viewport = el('div', px('toast-viewport'))\r\n document.body.appendChild(viewport)\r\n }\r\n return viewport\r\n }\r\n function dismiss(id: string): void {\r\n const timer = timers.get(id)\r\n if (timer) clearTimeout(timer)\r\n timers.delete(id)\r\n document.getElementById(id)?.remove()\r\n }\r\n function show(options: ToastOptions): string {\r\n const id = `linteau-toast-${++idCounter}`\r\n const variant = options.variant ?? 'default'\r\n const duration = options.duration ?? 4000\r\n const toastEl = el('div', cx(px('toast'), px(`toast-${variant}`)))\r\n toastEl.id = id\r\n const body = el('div', px('toast-body'))\r\n if (options.title) {\r\n const title = el('div', px('toast-title'))\r\n title.textContent = options.title\r\n body.appendChild(title)\r\n }\r\n if (options.description) {\r\n const description = el('div', px('toast-description'))\r\n description.textContent = options.description\r\n body.appendChild(description)\r\n }\r\n const closeButton = el('button', px('toast-close'))\r\n closeButton.type = 'button'\r\n const closeIcon = Icon(icons.x, 14)\r\n if (closeIcon) closeButton.appendChild(closeIcon)\r\n closeButton.addEventListener('click', () => dismiss(id))\r\n toastEl.append(body, closeButton)\r\n ensureViewport().appendChild(toastEl)\r\n if (duration > 0) timers.set(id, setTimeout(() => dismiss(id), duration))\r\n return id\r\n }\r\n return {\r\n show,\r\n dismiss,\r\n clear() {\r\n timers.forEach((timer) => clearTimeout(timer))\r\n timers.clear()\r\n viewport?.replaceChildren()\r\n },\r\n destroy() {\r\n timers.forEach((timer) => clearTimeout(timer))\r\n timers.clear()\r\n viewport?.remove()\r\n viewport = null\r\n }\r\n }\r\n}\r\n\r\n/** A ready-to-use shared toast manager: `toast.show({ title: 'Saved' })`. */\r\nexport const toast: ToastManager = createToastManager()","/**\r\n * CSS shared by every labeled field-style component (TextField, TextArea, NumberField,\r\n * ColorField, ChipInput, DatePicker, Select, Combobox, Slider, RangeSlider, Switch).\r\n *\r\n * Every one of those calls `ensureComponentStyles('field-base', fieldBaseCss)` before its\r\n * own specific CSS -- the key dedupes, so this is injected once no matter how many\r\n * field-style components an app uses.\r\n */\r\nexport const fieldBaseCss = `\r\n.linteau-field { display: flex; flex-direction: column; gap: 6px; width: 100% }\r\n.linteau-field-row { display: flex; align-items: center; justify-content: space-between }\r\n.linteau-field-label { display: flex; align-items: center; gap: 6px; color: var(--linteau-foreground) }\r\n.linteau-field-value { color: var(--linteau-muted-foreground); font-variant-numeric: tabular-nums }\r\n.linteau-field-header { display: flex; justify-content: space-between; align-items: center; font-size: 12px }\r\n`","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from './shared'\r\n\r\n/** Options accepted by the `ColorField` factory. */\r\nexport interface ColorFieldOptions {\r\n /** Label rendered before the swatch. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Controlled hex value. When provided together with `onChange`, you own the state. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. Defaults to `'#ffffff'`. */\r\n defaultValue?: string\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called on every color change. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `ColorField` element. */\r\nexport interface ColorFieldApi {\r\n /** Returns the current hex color string. */\r\n getValue: () => string\r\n /** Programmatically sets the color (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Enables/disables the control. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the field from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ColorField` is a real `HTMLDivElement` (the field row) extended with `ColorFieldApi`. */\r\nexport type ColorFieldElement = HTMLDivElement & ColorFieldApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const swatchCss = `\r\n.linteau-swatch { --linteau-swatch-color: #ffffff; width: 28px; height: 28px; border-radius: var(--linteau-radius-sm); background: var(--linteau-swatch-color); border: 1px solid var(--linteau-border); cursor: pointer; display: block; position: relative; overflow: hidden; transition: transform 120ms ease }\r\n.linteau-swatch:hover { transform: scale(1.06) }\r\n.linteau-swatch input[type='color'] { position: absolute; inset: 0; opacity: 0; cursor: pointer }\r\n`\r\n\r\n/** Creates a labeled native color-picker swatch, supporting controlled and uncontrolled usage. */\r\nexport function ColorField(options: ColorFieldOptions): ColorFieldElement {\r\n assertDom('ColorField')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('swatch', swatchCss)\r\n let value = options.value ?? options.defaultValue ?? '#ffffff'\r\n const onChange = options.onChange\r\n const root = el('div', px('field-row'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n const swatch = el('label', px('swatch'))\r\n swatch.style.setProperty('--linteau-swatch-color', value)\r\n const input = el('input', undefined)\r\n input.type = 'color'\r\n input.value = value\r\n input.disabled = options.disabled ?? false\r\n const listener = (): void => {\r\n value = input.value\r\n swatch.style.setProperty('--linteau-swatch-color', value)\r\n onChange?.(value)\r\n }\r\n input.addEventListener('input', listener)\r\n swatch.appendChild(input)\r\n root.append(labelWrap, swatch)\r\n const api: ColorFieldApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n input.value = newValue\r\n swatch.style.setProperty('--linteau-swatch-color', newValue)\r\n },\r\n setDisabled(disabled) {\r\n input.disabled = disabled\r\n },\r\n destroy() {\r\n input.removeEventListener('input', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","/**\r\n * CSS shared by every plain text-style input (TextField, TextArea, NumberField, and the\r\n * text inputs inside Combobox/DatePicker). Registered under the `text-input` key.\r\n */\r\nexport const textInputCss = `\r\n.linteau-text-input, .linteau-textarea {\r\n width: 100%;\r\n background: var(--linteau-secondary);\r\n color: var(--linteau-foreground);\r\n border: 1px solid var(--linteau-border);\r\n border-radius: var(--linteau-radius-sm);\r\n padding: 8px 10px;\r\n font-size: 12px;\r\n font-family: inherit;\r\n transition: border-color 120ms ease;\r\n}\r\n.linteau-text-input:focus, .linteau-textarea:focus {\r\n outline: none;\r\n border-color: var(--linteau-ring);\r\n box-shadow: 0 0 0 2px color-mix(in oklch, var(--linteau-ring) 20%, transparent);\r\n}\r\n.linteau-text-input:disabled, .linteau-textarea:disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-textarea { resize: vertical; min-height: 72px }\r\n`","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from './shared'\r\nimport { textInputCss } from './textInput.css'\r\n\r\n/** Options accepted by the `NumberField` factory. */\r\nexport interface NumberFieldOptions {\r\n /** Label rendered above the input. */\r\n label?: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Minimum allowed value. */\r\n min?: number\r\n /** Maximum allowed value. */\r\n max?: number\r\n /** Step increment used by the native spinner arrows. Defaults to `1`. */\r\n step?: number\r\n /** Controlled value. */\r\n value?: number\r\n /** Uncontrolled initial value, used only if `value` is omitted. Defaults to `0`. */\r\n defaultValue?: number\r\n /** Disables the input. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called on every valid numeric change. */\r\n onChange?: (value: number) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `NumberField` element. */\r\nexport interface NumberFieldApi {\r\n /** Returns the current numeric value. */\r\n getValue: () => number\r\n /** Programmatically sets the value, clamped to `[min, max]` if provided. */\r\n setValue: (value: number) => void\r\n /** Enables/disables the input. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the field from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `NumberField` is a real `HTMLDivElement` (the field wrapper) extended with `NumberFieldApi`. */\r\nexport type NumberFieldElement = HTMLDivElement & NumberFieldApi\r\n\r\n/**\r\n * Creates a labeled numeric input, supporting controlled and uncontrolled usage.\r\n *\r\n * This component has no CSS of its own -- it's fully covered by the shared `field-base`\r\n * and `text-input` blocks, so it registers those keys and nothing else.\r\n */\r\nexport function NumberField(options: NumberFieldOptions = {}): NumberFieldElement {\r\n assertDom('NumberField')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('text-input', textInputCss)\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n if (options.label) {\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n root.appendChild(header)\r\n }\r\n const input = el('input', px('text-input'))\r\n input.type = 'number'\r\n if (options.min !== undefined) input.min = String(options.min)\r\n if (options.max !== undefined) input.max = String(options.max)\r\n input.step = String(options.step ?? 1)\r\n input.value = String(options.value ?? options.defaultValue ?? 0)\r\n input.disabled = options.disabled ?? false\r\n function clamp(value: number): number {\r\n let result = value\r\n if (options.min !== undefined) result = Math.max(options.min, result)\r\n if (options.max !== undefined) result = Math.min(options.max, result)\r\n return result\r\n }\r\n const listener = (): void => {\r\n const parsed = Number(input.value)\r\n if (!Number.isNaN(parsed)) onChange?.(parsed)\r\n }\r\n input.addEventListener('input', listener)\r\n root.appendChild(input)\r\n const api: NumberFieldApi = {\r\n getValue() {\r\n return Number(input.value)\r\n },\r\n setValue(value) {\r\n input.value = String(clamp(value))\r\n },\r\n setDisabled(disabled) {\r\n input.disabled = disabled\r\n },\r\n destroy() {\r\n input.removeEventListener('input', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from './shared'\r\nimport { textInputCss } from './textInput.css'\r\n\r\n/** Options accepted by the `TextArea` factory. */\r\nexport interface TextAreaOptions {\r\n /** Label rendered above the textarea. */\r\n label?: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Placeholder text. */\r\n placeholder?: string\r\n /** Visible row count. Defaults to `3`. */\r\n rows?: number\r\n /** Controlled value. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: string\r\n /** Disables the textarea. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called on every keystroke with the new value. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `TextArea` element. */\r\nexport interface TextAreaApi {\r\n /** Returns the current value. */\r\n getValue: () => string\r\n /** Programmatically sets the value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Enables/disables the textarea. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the field from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `TextArea` is a real `HTMLDivElement` (the field wrapper) extended with `TextAreaApi`. */\r\nexport type TextAreaElement = HTMLDivElement & TextAreaApi\r\n\r\n/** Creates a labeled multi-line text input, supporting controlled and uncontrolled usage. */\r\nexport function TextArea(options: TextAreaOptions = {}): TextAreaElement {\r\n assertDom('TextArea')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('text-input', textInputCss)\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n if (options.label) {\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n root.appendChild(header)\r\n }\r\n const textarea = el('textarea', px('textarea'))\r\n textarea.placeholder = options.placeholder ?? ''\r\n textarea.rows = options.rows ?? 3\r\n textarea.value = options.value ?? options.defaultValue ?? ''\r\n textarea.disabled = options.disabled ?? false\r\n const listener = (): void => onChange?.(textarea.value)\r\n textarea.addEventListener('input', listener)\r\n root.appendChild(textarea)\r\n const api: TextAreaApi = {\r\n getValue() {\r\n return textarea.value\r\n },\r\n setValue(value) {\r\n textarea.value = value\r\n },\r\n setDisabled(disabled) {\r\n textarea.disabled = disabled\r\n },\r\n destroy() {\r\n textarea.removeEventListener('input', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from './shared'\r\nimport { textInputCss } from './textInput.css'\r\n\r\n/** Options accepted by the `TextField` factory. */\r\nexport interface TextFieldOptions {\r\n /** Label rendered above the input. */\r\n label?: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Native input type. Defaults to `'text'`. */\r\n type?: 'text' | 'email' | 'password' | 'search' | 'tel' | 'url'\r\n /** Placeholder text. */\r\n placeholder?: string\r\n /** Controlled value. When provided together with `onChange`, you own the state. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: string\r\n /** Disables the input. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called on every keystroke with the new value. */\r\n onChange?: (value: string) => void\r\n /** Called when Enter is pressed. */\r\n onEnter?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `TextField` element. */\r\nexport interface TextFieldApi {\r\n /** Returns the current input value. */\r\n getValue: () => string\r\n /** Programmatically sets the value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Enables/disables the input. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Focuses the underlying input. */\r\n focus: () => void\r\n /** Detaches the field from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `TextField` is a real `HTMLDivElement` (the field wrapper) extended with `TextFieldApi`. */\r\nexport type TextFieldElement = HTMLDivElement & TextFieldApi\r\n\r\n/** Creates a labeled single-line text input, supporting controlled and uncontrolled usage. */\r\nexport function TextField(options: TextFieldOptions = {}): TextFieldElement {\r\n assertDom('TextField')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('text-input', textInputCss)\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n if (options.label) {\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n root.appendChild(header)\r\n }\r\n const input = el('input', px('text-input'))\r\n input.type = options.type ?? 'text'\r\n input.placeholder = options.placeholder ?? ''\r\n input.value = options.value ?? options.defaultValue ?? ''\r\n input.disabled = options.disabled ?? false\r\n const inputListener = (): void => onChange?.(input.value)\r\n const keyListener = (event: KeyboardEvent): void => { if (event.key === 'Enter') options.onEnter?.(input.value) }\r\n input.addEventListener('input', inputListener)\r\n input.addEventListener('keydown', keyListener)\r\n root.appendChild(input)\r\n const api: TextFieldApi = {\r\n getValue() {\r\n return input.value\r\n },\r\n setValue(value) {\r\n input.value = value\r\n },\r\n setDisabled(disabled) {\r\n input.disabled = disabled\r\n },\r\n focus() {\r\n input.focus()\r\n },\r\n destroy() {\r\n input.removeEventListener('input', inputListener)\r\n input.removeEventListener('keydown', keyListener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","/** Replaces `target`'s children with either an appended element or plain text. Shared by every component with a \"content\" slot. */\r\nexport function fillContent(target: HTMLElement, content: HTMLElement | string): void {\r\n target.replaceChildren()\r\n if (content instanceof HTMLElement) target.appendChild(content)\r\n else target.textContent = content\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { positionFloating } from '../../core/overlay'\r\nimport type { FloatingPlacement } from '../../core/overlay'\r\nimport { fillContent } from '../../core/content'\r\nimport type { Destroyable } from '../../core/types'\r\n\r\n/** Options accepted by the `HoverCard` factory. */\r\nexport interface HoverCardOptions {\r\n /** The element that triggers the card on hover/focus. */\r\n anchor: HTMLElement\r\n /** Initial card content -- can hold interactive elements, unlike `Tooltip`. */\r\n content: HTMLElement | string\r\n /** Side of the anchor the card appears on. Defaults to `'bottom'`. */\r\n placement?: FloatingPlacement\r\n /** Milliseconds to wait before showing, after hover/focus starts. Defaults to `300`. */\r\n openDelay?: number\r\n /** Milliseconds to wait before hiding, after the pointer leaves both the anchor and the card. Defaults to `150`. */\r\n closeDelay?: number\r\n}\r\n\r\n/**\r\n * The runtime control surface returned by `HoverCard`. Like `Tooltip`, this is a plain\r\n * controller -- not an element -- since it attaches behavior to an existing anchor.\r\n */\r\nexport interface HoverCardApi extends Destroyable {\r\n /** Replaces the card's content. */\r\n setContent: (content: HTMLElement | string) => void\r\n /** Opens the card immediately, bypassing `openDelay`. */\r\n open: () => void\r\n /** Closes the card immediately, bypassing `closeDelay`. */\r\n close: () => void\r\n}\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const hoverCardCss = `\r\n.linteau-hover-card { position: fixed; z-index: 1200; width: 280px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-md); padding: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); font-size: 12px; color: var(--linteau-foreground) }\r\n`\r\n\r\n/**\r\n * Attaches a floating rich-content card to `anchor`, shown on hover/focus with a delay in\r\n * each direction. Unlike `Tooltip`, the card stays open while the pointer moves into it --\r\n * so it can safely contain links, buttons, or other interactive content.\r\n */\r\nexport function HoverCard(options: HoverCardOptions): HoverCardApi {\r\n assertDom('HoverCard')\r\n ensureComponentStyles('hover-card', hoverCardCss)\r\n const { anchor, placement = 'bottom' } = options\r\n const openDelay = options.openDelay ?? 300\r\n const closeDelay = options.closeDelay ?? 150\r\n let openTimer: ReturnType<typeof setTimeout> | null = null\r\n let closeTimer: ReturnType<typeof setTimeout> | null = null\r\n let isVisible = false\r\n const card = el('div', cx(px('hover-card'), px('hidden')))\r\n fillContent(card, options.content)\r\n function clearTimers(): void {\r\n if (openTimer) clearTimeout(openTimer)\r\n if (closeTimer) clearTimeout(closeTimer)\r\n openTimer = null\r\n closeTimer = null\r\n }\r\n function showNow(): void {\r\n clearTimers()\r\n if (isVisible) return\r\n isVisible = true\r\n document.body.appendChild(card)\r\n card.classList.remove(px('hidden'))\r\n positionFloating(anchor, card, placement)\r\n }\r\n function hideNow(): void {\r\n clearTimers()\r\n if (!isVisible) return\r\n isVisible = false\r\n card.classList.add(px('hidden'))\r\n card.remove()\r\n }\r\n function scheduleShow(): void {\r\n if (closeTimer) clearTimeout(closeTimer)\r\n closeTimer = null\r\n if (isVisible || openTimer) return\r\n openTimer = setTimeout(showNow, openDelay)\r\n }\r\n function scheduleHide(): void {\r\n if (openTimer) clearTimeout(openTimer)\r\n openTimer = null\r\n if (!isVisible || closeTimer) return\r\n closeTimer = setTimeout(hideNow, closeDelay)\r\n }\r\n anchor.addEventListener('mouseenter', scheduleShow)\r\n anchor.addEventListener('mouseleave', scheduleHide)\r\n anchor.addEventListener('focus', scheduleShow)\r\n anchor.addEventListener('blur', scheduleHide)\r\n card.addEventListener('mouseenter', () => { if (closeTimer) clearTimeout(closeTimer); closeTimer = null })\r\n card.addEventListener('mouseleave', scheduleHide)\r\n return {\r\n setContent(content) {\r\n fillContent(card, content)\r\n },\r\n open: showNow,\r\n close: hideNow,\r\n destroy() {\r\n clearTimers()\r\n anchor.removeEventListener('mouseenter', scheduleShow)\r\n anchor.removeEventListener('mouseleave', scheduleHide)\r\n anchor.removeEventListener('focus', scheduleShow)\r\n anchor.removeEventListener('blur', scheduleHide)\r\n card.remove()\r\n }\r\n }\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\n\r\n/** Options accepted by the `ChipInput` factory. */\r\nexport interface ChipInputOptions {\r\n /** Label rendered above the field. */\r\n label?: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Controlled list of chip values. */\r\n value?: string[]\r\n /** Uncontrolled initial values, used only if `value` is omitted. */\r\n defaultValue?: string[]\r\n /** Placeholder shown in the text input. */\r\n placeholder?: string\r\n /** Called whenever a chip is added or removed. */\r\n onChange?: (value: string[]) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `ChipInput` element. */\r\nexport interface ChipInputApi {\r\n /** Returns the current list of chip values. */\r\n getValue: () => string[]\r\n /** Programmatically replaces the chip list (does not trigger `onChange`). */\r\n setValue: (value: string[]) => void\r\n /** Detaches the field from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ChipInput` is a real `HTMLDivElement` (the field wrapper) extended with `ChipInputApi`. */\r\nexport type ChipInputElement = HTMLDivElement & ChipInputApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const chipInputCss = `\r\n.linteau-chip-field { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px; background: var(--linteau-secondary); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-sm) }\r\n.linteau-chip-field:focus-within { border-color: var(--linteau-ring) }\r\n.linteau-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--linteau-accent); color: var(--linteau-accent-foreground); border-radius: 999px; padding: 3px 8px; font-size: 11px }\r\n.linteau-chip-remove { background: transparent; border: none; color: inherit; cursor: pointer; display: flex; padding: 0 }\r\n.linteau-chip-input { flex: 1; min-width: 80px; background: transparent; border: none; color: var(--linteau-foreground); font-size: 12px; font-family: inherit; outline: none }\r\n`\r\n\r\n/** Creates a labeled tag/chip input: press Enter to add the typed text as a removable chip. */\r\nexport function ChipInput(options: ChipInputOptions = {}): ChipInputElement {\r\n assertDom('ChipInput')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('chip-input', chipInputCss)\r\n let chips = options.value ?? options.defaultValue ?? []\r\n const onChange = options.onChange\r\n const cleanupChipListeners: Array<() => void> = []\r\n const root = el('div', px('field'))\r\n if (options.label) {\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n root.appendChild(header)\r\n }\r\n const fieldWrap = el('div', px('chip-field'))\r\n const input = el('input', px('chip-input'))\r\n input.type = 'text'\r\n input.placeholder = options.placeholder ?? ''\r\n fieldWrap.appendChild(input)\r\n function renderChips(): void {\r\n Array.from(fieldWrap.children).forEach((child) => { if (child !== input) child.remove() })\r\n cleanupChipListeners.splice(0).forEach((fn) => fn())\r\n chips.forEach((value, index) => {\r\n const chip = el('span', px('chip'))\r\n const label = document.createElement('span')\r\n label.textContent = value\r\n const removeButton = el('button', px('chip-remove'))\r\n removeButton.type = 'button'\r\n const removeIcon = Icon(icons.x, 10)\r\n if (removeIcon) removeButton.appendChild(removeIcon)\r\n const listener = (): void => {\r\n chips = chips.filter((_, i) => i !== index)\r\n renderChips()\r\n onChange?.(chips)\r\n }\r\n removeButton.addEventListener('click', listener)\r\n cleanupChipListeners.push(() => removeButton.removeEventListener('click', listener))\r\n chip.append(label, removeButton)\r\n fieldWrap.insertBefore(chip, input)\r\n })\r\n }\r\n renderChips()\r\n const keyListener = (event: KeyboardEvent): void => {\r\n if (event.key === 'Enter' && input.value.trim()) {\r\n event.preventDefault()\r\n chips = [...chips, input.value.trim()]\r\n input.value = ''\r\n renderChips()\r\n onChange?.(chips)\r\n } else if (event.key === 'Backspace' && !input.value && chips.length > 0) {\r\n chips = chips.slice(0, -1)\r\n renderChips()\r\n onChange?.(chips)\r\n }\r\n }\r\n input.addEventListener('keydown', keyListener)\r\n root.appendChild(fieldWrap)\r\n const api: ChipInputApi = {\r\n getValue() {\r\n return chips\r\n },\r\n setValue(newValue) {\r\n chips = newValue\r\n renderChips()\r\n },\r\n destroy() {\r\n input.removeEventListener('keydown', keyListener)\r\n cleanupChipListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onClickOutside, positionFloating } from '../../core/overlay'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\nimport type { SelectOptionItem } from './Select'\r\nimport { fieldBaseCss } from '../field/shared'\r\nimport { textInputCss } from '../field/textInput.css'\r\n\r\n/** Options accepted by the `Combobox` factory. */\r\nexport interface ComboboxOptions {\r\n /** Label rendered above the field. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** The list of selectable options, filtered live against the typed text. */\r\n options: SelectOptionItem[]\r\n /** Controlled value. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: string\r\n /** Placeholder shown when nothing is typed/selected. */\r\n placeholder?: string\r\n /** Disables the field. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user selects an option. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Combobox` element. */\r\nexport interface ComboboxApi {\r\n /** Returns the currently selected value. */\r\n getValue: () => string\r\n /** Programmatically selects a value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Replaces the full list of options. */\r\n setOptions: (options: SelectOptionItem[]) => void\r\n /** Opens the suggestion list. */\r\n open: () => void\r\n /** Closes the suggestion list. */\r\n close: () => void\r\n /** Detaches the field from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Combobox` is a real `HTMLDivElement` (the field wrapper) extended with `ComboboxApi`. */\r\nexport type ComboboxElement = HTMLDivElement & ComboboxApi\r\n\r\n/** This component's own CSS. Reused by `DatePicker` under the same `combobox` key, so it's only ever injected once. */\r\nexport const comboboxCss = `\r\n.linteau-combobox { position: relative; display: flex; align-items: center }\r\n.linteau-combobox-input { padding-right: 28px }\r\n.linteau-combobox-chevron { position: absolute; right: 8px; pointer-events: none; color: var(--linteau-muted-foreground) }\r\n.linteau-combobox-list { position: fixed; z-index: 1200; min-width: 180px; max-height: 220px; overflow-y: auto; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-md); padding: 4px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) }\r\n.linteau-combobox-option { padding: 6px 8px; border-radius: var(--linteau-radius-sm); font-size: 12px; cursor: pointer; color: var(--linteau-foreground) }\r\n.linteau-combobox-option-highlighted, .linteau-combobox-option:hover { background: var(--linteau-accent) }\r\n`\r\n\r\n/** Creates a filterable, type-to-search select -- a text input backed by a live-filtered dropdown of options. */\r\nexport function Combobox(options: ComboboxOptions): ComboboxElement {\r\n assertDom('Combobox')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('text-input', textInputCss)\r\n ensureComponentStyles('combobox', comboboxCss)\r\n let items = options.options\r\n let value = options.value ?? options.defaultValue ?? ''\r\n let query = items.find((item) => item.value === value)?.label ?? ''\r\n let isOpen = false\r\n let highlighted = 0\r\n let unbindOutside: (() => void) | null = null\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n const wrap = el('div', px('combobox'))\r\n const input = el('input', cx(px('text-input'), px('combobox-input')))\r\n input.type = 'text'\r\n input.placeholder = options.placeholder ?? ''\r\n input.value = query\r\n input.disabled = options.disabled ?? false\r\n const chevron = Icon(icons.chevronDown, 12, { className: px('combobox-chevron') })!\r\n const list = el('div', cx(px('combobox-list'), px('hidden')))\r\n function filtered(): SelectOptionItem[] {\r\n const normalized = query.trim().toLowerCase()\r\n if (!normalized) return items\r\n return items.filter((item) => item.label.toLowerCase().includes(normalized))\r\n }\r\n function renderList(): void {\r\n list.replaceChildren()\r\n filtered().forEach((item, index) => {\r\n const optionEl = el('div', cx(px('combobox-option'), index === highlighted && px('combobox-option-highlighted')))\r\n optionEl.textContent = item.label\r\n optionEl.addEventListener('mousedown', (event) => {\r\n event.preventDefault()\r\n select(item)\r\n })\r\n list.appendChild(optionEl)\r\n })\r\n }\r\n function select(item: SelectOptionItem): void {\r\n value = item.value\r\n query = item.label\r\n input.value = query\r\n close()\r\n onChange?.(value)\r\n }\r\n function open(): void {\r\n if (isOpen || input.disabled) return\r\n isOpen = true\r\n highlighted = 0\r\n document.body.appendChild(list)\r\n list.classList.remove(px('hidden'))\r\n renderList()\r\n positionFloating(wrap, list, 'bottom')\r\n unbindOutside = onClickOutside([wrap, list], close)\r\n }\r\n function close(): void {\r\n if (!isOpen) return\r\n isOpen = false\r\n list.classList.add(px('hidden'))\r\n list.remove()\r\n unbindOutside?.()\r\n unbindOutside = null\r\n }\r\n const inputListener = (): void => {\r\n query = input.value\r\n highlighted = 0\r\n if (!isOpen) open()\r\n else renderList()\r\n }\r\n const keyListener = (event: KeyboardEvent): void => {\r\n const results = filtered()\r\n if (event.key === 'ArrowDown') {\r\n event.preventDefault()\r\n highlighted = Math.min(highlighted + 1, results.length - 1)\r\n renderList()\r\n } else if (event.key === 'ArrowUp') {\r\n event.preventDefault()\r\n highlighted = Math.max(highlighted - 1, 0)\r\n renderList()\r\n } else if (event.key === 'Enter') {\r\n event.preventDefault()\r\n const item = results[highlighted]\r\n if (item) select(item)\r\n } else if (event.key === 'Escape') {\r\n close()\r\n }\r\n }\r\n const focusListener = (): void => open()\r\n input.addEventListener('input', inputListener)\r\n input.addEventListener('keydown', keyListener)\r\n input.addEventListener('focus', focusListener)\r\n wrap.append(input, chevron)\r\n root.append(header, wrap)\r\n const api: ComboboxApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n query = items.find((item) => item.value === newValue)?.label ?? ''\r\n input.value = query\r\n },\r\n setOptions(newOptions) {\r\n items = newOptions\r\n if (isOpen) renderList()\r\n },\r\n open,\r\n close,\r\n destroy() {\r\n input.removeEventListener('input', inputListener)\r\n input.removeEventListener('keydown', keyListener)\r\n input.removeEventListener('focus', focusListener)\r\n unbindOutside?.()\r\n list.remove()\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onClickOutside, onEscapeKey, positionFloating } from '../../core/overlay'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\nimport { textInputCss } from '../field/textInput.css'\r\nimport { comboboxCss } from '../select/Combobox'\r\n\r\n/** Which single day of the week a calendar week starts on. `0` = Sunday, `1` = Monday. */\r\nexport type WeekStartsOn = 0 | 1\r\n\r\n/** A `from`/`to` date pair used when `mode` is `'range'`. `to` is `undefined` while the second endpoint hasn't been picked yet. */\r\nexport interface DateRange {\r\n /** The earlier bound of the range. */\r\n from: Date\r\n /** The later bound of the range, or `undefined` mid-selection. */\r\n to?: Date\r\n}\r\n\r\n/** Options accepted by the `DatePicker` factory. */\r\nexport interface DatePickerOptions {\r\n /** Label rendered above the field. */\r\n label?: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** `'single'` picks one date; `'range'` picks a `from`/`to` pair. Defaults to `'single'`. */\r\n mode?: 'single' | 'range'\r\n /** Controlled selected value -- a `Date` in `'single'` mode, a `DateRange` in `'range'` mode. */\r\n value?: Date | DateRange\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: Date | DateRange\r\n /** Earliest selectable date, inclusive. */\r\n min?: Date\r\n /** Latest selectable date, inclusive. */\r\n max?: Date\r\n /** Which day starts each calendar week. Defaults to `0` (Sunday). */\r\n weekStartsOn?: WeekStartsOn\r\n /** Formats a single date for display. Defaults to `Date.prototype.toLocaleDateString`. */\r\n format?: (date: Date) => string\r\n /** Placeholder shown when nothing is selected. Defaults to `'Select a date'` (or `'Select a date range'` in range mode). */\r\n placeholder?: string\r\n /** Disables the whole field. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Shows a \"Today\" quick-jump button in the footer. Defaults to `true`. */\r\n showTodayButton?: boolean\r\n /** Shows a \"Clear\" button in the footer once a value is selected. Defaults to `true`. */\r\n showClearButton?: boolean\r\n /** Called whenever the selection changes (including clears, which pass `undefined`). */\r\n onChange?: (value: Date | DateRange | undefined) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `DatePicker` element. */\r\nexport interface DatePickerApi {\r\n /** Returns the currently selected value, if any. */\r\n getValue: () => Date | DateRange | undefined\r\n /** Programmatically sets the value (does not trigger `onChange`). */\r\n setValue: (value: Date | DateRange | undefined) => void\r\n /** Opens the calendar popover. */\r\n open: () => void\r\n /** Closes the calendar popover. */\r\n close: () => void\r\n /** Returns whether the calendar popover is currently open. */\r\n isOpen: () => boolean\r\n /** Detaches the field from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `DatePicker` is a real `HTMLDivElement` (the field wrapper) extended with `DatePickerApi`. */\r\nexport type DatePickerElement = HTMLDivElement & DatePickerApi\r\n\r\n/** This component's own CSS -- the calendar popover, weekday header, range highlighting, and footer actions. Depends on `.linteau-combobox` (registered via the imported `comboboxCss`). */\r\nexport const calendarCss = `\r\n.linteau-calendar { position: fixed; z-index: 1200; width: 280px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); padding: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) }\r\n.linteau-calendar-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px }\r\n.linteau-calendar-nav { background: transparent; border: none; color: var(--linteau-foreground); cursor: pointer; display: flex; padding: 4px; border-radius: var(--linteau-radius-sm) }\r\n.linteau-calendar-nav:hover:not(:disabled) { background: var(--linteau-accent) }\r\n.linteau-calendar-nav:disabled { opacity: 0.35; cursor: not-allowed }\r\n.linteau-calendar-month { font-size: 12px; font-weight: 600 }\r\n.linteau-calendar-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 2px }\r\n.linteau-calendar-weekday { height: 20px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: var(--linteau-muted-foreground); text-transform: uppercase }\r\n.linteau-calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px }\r\n.linteau-calendar-day { height: 28px; display: flex; align-items: center; justify-content: center; font-size: 11px; border-radius: var(--linteau-radius-sm); background: transparent; border: none; color: var(--linteau-foreground); cursor: pointer; font-family: inherit }\r\n.linteau-calendar-day:hover:not(:disabled) { background: var(--linteau-accent) }\r\n.linteau-calendar-day:disabled { opacity: 0.35; cursor: not-allowed }\r\n.linteau-calendar-day:focus-visible { outline: 2px solid var(--linteau-ring); outline-offset: 1px }\r\n.linteau-calendar-day-outside { opacity: 0.35 }\r\n.linteau-calendar-day-selected { background: var(--linteau-primary); color: var(--linteau-primary-foreground) }\r\n.linteau-calendar-day-today:not(.linteau-calendar-day-selected) { box-shadow: inset 0 0 0 1px var(--linteau-ring) }\r\n.linteau-calendar-day-in-range { background: var(--linteau-accent); border-radius: 0 }\r\n.linteau-calendar-day-range-start { background: var(--linteau-primary); color: var(--linteau-primary-foreground); border-radius: var(--linteau-radius-sm) 0 0 var(--linteau-radius-sm) }\r\n.linteau-calendar-day-range-end { background: var(--linteau-primary); color: var(--linteau-primary-foreground); border-radius: 0 var(--linteau-radius-sm) var(--linteau-radius-sm) 0 }\r\n.linteau-calendar-footer { display: flex; gap: 6px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--linteau-border) }\r\n.linteau-calendar-footer-button { flex: 1; padding: 6px 8px; font-size: 11px; border-radius: var(--linteau-radius-sm); border: 1px solid var(--linteau-border); background: transparent; color: var(--linteau-foreground); cursor: pointer; font-family: inherit }\r\n.linteau-calendar-footer-button:hover { background: var(--linteau-accent) }\r\n.linteau-combobox-input-clearable { padding-right: 46px }\r\n.linteau-combobox-clear { position: absolute; right: 26px; color: var(--linteau-muted-foreground); background: transparent; border: none; cursor: pointer; display: flex; padding: 2px }\r\n.linteau-combobox-clear:hover { color: var(--linteau-foreground) }\r\n`\r\n\r\nfunction isSameDay(a: Date, b: Date): boolean {\r\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\r\n}\r\n\r\nfunction startOfMonth(date: Date): Date {\r\n return new Date(date.getFullYear(), date.getMonth(), 1)\r\n}\r\n\r\nfunction addMonths(date: Date, count: number): Date {\r\n return new Date(date.getFullYear(), date.getMonth() + count, 1)\r\n}\r\n\r\nfunction addDays(date: Date, count: number): Date {\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + count)\r\n}\r\n\r\nfunction isRange(value: Date | DateRange | undefined): value is DateRange {\r\n return Boolean(value) && typeof value === 'object' && 'from' in (value as object)\r\n}\r\n\r\nfunction buildWeekdayLabels(weekStartsOn: WeekStartsOn): string[] {\r\n const base = new Date(2021, 0, 3) // a Sunday\r\n const labels: string[] = []\r\n for (let i = 0; i < 7; i++) {\r\n const day = new Date(base.getFullYear(), base.getMonth(), base.getDate() + i + weekStartsOn)\r\n labels.push(day.toLocaleDateString(undefined, { weekday: 'short' }).slice(0, 2))\r\n }\r\n return labels\r\n}\r\n\r\nfunction getCalendarDays(viewDate: Date, weekStartsOn: WeekStartsOn): Array<{ date: Date, inCurrentMonth: boolean }> {\r\n const year = viewDate.getFullYear()\r\n const month = viewDate.getMonth()\r\n const firstOfMonth = new Date(year, month, 1)\r\n const lastOfMonth = new Date(year, month + 1, 0)\r\n const leadingOffset = (firstOfMonth.getDay() - weekStartsOn + 7) % 7\r\n const trailingOffset = (weekStartsOn + 6 - lastOfMonth.getDay() + 7) % 7\r\n const days: Array<{ date: Date, inCurrentMonth: boolean }> = []\r\n for (let i = leadingOffset; i > 0; i--) days.push({ date: new Date(year, month, 1 - i), inCurrentMonth: false })\r\n for (let day = 1; day <= lastOfMonth.getDate(); day++) days.push({ date: new Date(year, month, day), inCurrentMonth: true })\r\n for (let i = 1; i <= trailingOffset; i++) days.push({ date: new Date(year, month + 1, i), inCurrentMonth: false })\r\n return days\r\n}\r\n\r\n/**\r\n * Creates a labeled date (or date-range) field backed by a floating month-grid calendar\r\n * popover with weekday headers, outside-month days, range selection with hover preview,\r\n * full keyboard navigation, and Today/Clear quick actions.\r\n */\r\nexport function DatePicker(options: DatePickerOptions = {}): DatePickerElement {\r\n assertDom('DatePicker')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('text-input', textInputCss)\r\n ensureComponentStyles('combobox', comboboxCss)\r\n ensureComponentStyles('calendar', calendarCss)\r\n const mode = options.mode ?? 'single'\r\n const weekStartsOn = options.weekStartsOn ?? 0\r\n const min = options.min\r\n const max = options.max\r\n const format = options.format ?? ((date: Date) => date.toLocaleDateString())\r\n const onChange = options.onChange\r\n const showTodayButton = options.showTodayButton ?? true\r\n const showClearButton = options.showClearButton ?? true\r\n let value = options.value ?? options.defaultValue\r\n let rangeAnchor: Date | null = null\r\n let viewDate = (isRange(value) ? value.from : value) ?? new Date()\r\n let focusedDate = viewDate\r\n let isOpen = false\r\n let unbindOutside: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const dayButtonsByTime = new Map<number, HTMLButtonElement>()\r\n\r\n function formatValue(v: Date | DateRange | undefined): string {\r\n if (!v) return ''\r\n if (isRange(v)) return v.to ? `${format(v.from)} - ${format(v.to)}` : format(v.from)\r\n return format(v)\r\n }\r\n\r\n function isDisabledDate(date: Date): boolean {\r\n return Boolean((min && date < min) || (max && date > max))\r\n }\r\n\r\n const root = el('div', px('field'))\r\n if (options.label) {\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n header.appendChild(labelWrap)\r\n root.appendChild(header)\r\n }\r\n const wrap = el('div', px('combobox'))\r\n const input = el('input', cx(px('text-input'), px('combobox-input')))\r\n input.type = 'text'\r\n input.readOnly = true\r\n input.value = formatValue(value)\r\n input.placeholder = options.placeholder ?? (mode === 'range' ? 'Select a date range' : 'Select a date')\r\n input.disabled = options.disabled ?? false\r\n const clearButton = el('button', px('combobox-clear'))\r\n clearButton.type = 'button'\r\n const clearIcon = Icon(icons.x, 12)\r\n if (clearIcon) clearButton.appendChild(clearIcon)\r\n const calendarIcon = Icon(icons.calendar, 14, { className: px('combobox-chevron') })!\r\n wrap.append(input, clearButton, calendarIcon)\r\n root.appendChild(wrap)\r\n\r\n function syncClearButton(): void {\r\n const hasValue = Boolean(value)\r\n clearButton.style.display = hasValue && showClearButton ? 'flex' : 'none'\r\n input.classList.toggle(px('combobox-input-clearable'), hasValue && showClearButton)\r\n }\r\n syncClearButton()\r\n\r\n const calendar = el('div', cx(px('calendar'), px('hidden')))\r\n calendar.setAttribute('role', 'application')\r\n\r\n function focusDayButton(date: Date): void {\r\n dayButtonsByTime.get(new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime())?.focus()\r\n }\r\n\r\n function updateHoverPreview(hovered: Date | null): void {\r\n if (mode !== 'range' || !rangeAnchor) return\r\n for (const [time, button] of dayButtonsByTime) {\r\n const date = new Date(time)\r\n const inPreview = hovered ? (date >= rangeAnchor && date <= hovered) || (date <= rangeAnchor && date >= hovered) : false\r\n button.classList.toggle(px('calendar-day-in-range'), inPreview && !isSameDay(date, rangeAnchor))\r\n }\r\n }\r\n\r\n function handleDayClick(date: Date): void {\r\n if (isDisabledDate(date)) return\r\n if (mode === 'range') {\r\n if (!rangeAnchor) {\r\n rangeAnchor = date\r\n value = { from: date }\r\n input.value = formatValue(value)\r\n renderCalendar()\r\n } else {\r\n const from = rangeAnchor <= date ? rangeAnchor : date\r\n const to = rangeAnchor <= date ? date : rangeAnchor\r\n value = { from, to }\r\n rangeAnchor = null\r\n input.value = formatValue(value)\r\n syncClearButton()\r\n onChange?.(value)\r\n close()\r\n }\r\n } else {\r\n value = date\r\n input.value = formatValue(value)\r\n syncClearButton()\r\n onChange?.(value)\r\n close()\r\n }\r\n }\r\n\r\n function renderCalendar(): void {\r\n calendar.replaceChildren()\r\n dayButtonsByTime.clear()\r\n const header = el('div', px('calendar-header'))\r\n const prevButton = el('button', px('calendar-nav'))\r\n prevButton.type = 'button'\r\n prevButton.setAttribute('aria-label', 'Previous month')\r\n const prevIcon = Icon(icons.chevronLeft, 14)\r\n if (prevIcon) prevButton.appendChild(prevIcon)\r\n prevButton.disabled = Boolean(min && addMonths(viewDate, -1) < startOfMonth(min))\r\n const nextButton = el('button', px('calendar-nav'))\r\n nextButton.type = 'button'\r\n nextButton.setAttribute('aria-label', 'Next month')\r\n const nextIcon = Icon(icons.chevronRight, 14)\r\n if (nextIcon) nextButton.appendChild(nextIcon)\r\n nextButton.disabled = Boolean(max && addMonths(viewDate, 1) > startOfMonth(max))\r\n const monthLabel = el('div', px('calendar-month'))\r\n monthLabel.textContent = viewDate.toLocaleDateString(undefined, { month: 'long', year: 'numeric' })\r\n prevButton.addEventListener('click', () => {\r\n viewDate = addMonths(viewDate, -1)\r\n renderCalendar()\r\n })\r\n nextButton.addEventListener('click', () => {\r\n viewDate = addMonths(viewDate, 1)\r\n renderCalendar()\r\n })\r\n header.append(prevButton, monthLabel, nextButton)\r\n const weekdaysRow = el('div', px('calendar-weekdays'))\r\n for (const label of buildWeekdayLabels(weekStartsOn)) {\r\n const cell = el('div', px('calendar-weekday'))\r\n cell.textContent = label\r\n weekdaysRow.appendChild(cell)\r\n }\r\n const grid = el('div', px('calendar-grid'))\r\n const today = new Date()\r\n for (const { date, inCurrentMonth } of getCalendarDays(viewDate, weekStartsOn)) {\r\n const dayButton = el('button', px('calendar-day'))\r\n dayButton.type = 'button'\r\n dayButton.textContent = String(date.getDate())\r\n dayButton.disabled = isDisabledDate(date)\r\n dayButton.tabIndex = isSameDay(date, focusedDate) ? 0 : -1\r\n if (!inCurrentMonth) dayButton.classList.add(px('calendar-day-outside'))\r\n if (isSameDay(date, today)) dayButton.classList.add(px('calendar-day-today'))\r\n const currentValue = value\r\n if (currentValue && !isRange(currentValue) && isSameDay(date, currentValue)) {\r\n dayButton.classList.add(px('calendar-day-selected'))\r\n dayButton.setAttribute('aria-selected', 'true')\r\n }\r\n if (currentValue && isRange(currentValue)) {\r\n if (isSameDay(date, currentValue.from)) dayButton.classList.add(px('calendar-day-range-start'), px('calendar-day-selected'))\r\n if (currentValue.to && isSameDay(date, currentValue.to)) dayButton.classList.add(px('calendar-day-range-end'), px('calendar-day-selected'))\r\n if (currentValue.to && date > currentValue.from && date < currentValue.to) dayButton.classList.add(px('calendar-day-in-range'))\r\n }\r\n dayButton.addEventListener('click', () => {\r\n focusedDate = date\r\n handleDayClick(date)\r\n })\r\n dayButton.addEventListener('mouseenter', () => updateHoverPreview(date))\r\n dayButtonsByTime.set(new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime(), dayButton)\r\n grid.appendChild(dayButton)\r\n }\r\n calendar.append(header, weekdaysRow, grid)\r\n if (showTodayButton || showClearButton) {\r\n const footer = el('div', px('calendar-footer'))\r\n if (showTodayButton) {\r\n const todayButton = el('button', px('calendar-footer-button'))\r\n todayButton.type = 'button'\r\n todayButton.textContent = 'Today'\r\n todayButton.addEventListener('click', () => {\r\n viewDate = startOfMonth(new Date())\r\n focusedDate = new Date()\r\n renderCalendar()\r\n focusDayButton(focusedDate)\r\n })\r\n footer.appendChild(todayButton)\r\n }\r\n if (showClearButton) {\r\n const clearFooterButton = el('button', px('calendar-footer-button'))\r\n clearFooterButton.type = 'button'\r\n clearFooterButton.textContent = 'Clear'\r\n clearFooterButton.addEventListener('click', () => {\r\n value = undefined\r\n rangeAnchor = null\r\n input.value = ''\r\n syncClearButton()\r\n onChange?.(undefined)\r\n renderCalendar()\r\n })\r\n footer.appendChild(clearFooterButton)\r\n }\r\n calendar.appendChild(footer)\r\n }\r\n }\r\n\r\n function handleKeydown(event: KeyboardEvent): void {\r\n const deltas: Record<string, number> = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 }\r\n if (event.key in deltas) {\r\n event.preventDefault()\r\n focusedDate = addDays(focusedDate, deltas[event.key] as number)\r\n if (focusedDate.getMonth() !== viewDate.getMonth() || focusedDate.getFullYear() !== viewDate.getFullYear()) viewDate = startOfMonth(focusedDate)\r\n renderCalendar()\r\n focusDayButton(focusedDate)\r\n } else if (event.key === 'PageUp') {\r\n event.preventDefault()\r\n viewDate = addMonths(viewDate, -1)\r\n renderCalendar()\r\n } else if (event.key === 'PageDown') {\r\n event.preventDefault()\r\n viewDate = addMonths(viewDate, 1)\r\n renderCalendar()\r\n } else if (event.key === 'Enter' || event.key === ' ') {\r\n event.preventDefault()\r\n handleDayClick(focusedDate)\r\n }\r\n }\r\n\r\n function open(): void {\r\n if (isOpen || input.disabled) return\r\n isOpen = true\r\n viewDate = (isRange(value) ? value.from : value) ?? viewDate\r\n focusedDate = viewDate\r\n document.body.appendChild(calendar)\r\n calendar.classList.remove(px('hidden'))\r\n renderCalendar()\r\n positionFloating(wrap, calendar, 'bottom')\r\n calendar.addEventListener('keydown', handleKeydown)\r\n unbindOutside = onClickOutside([wrap, calendar], close)\r\n unbindEscape = onEscapeKey(close)\r\n }\r\n function close(): void {\r\n if (!isOpen) return\r\n isOpen = false\r\n rangeAnchor = null\r\n calendar.classList.add(px('hidden'))\r\n calendar.removeEventListener('keydown', handleKeydown)\r\n calendar.remove()\r\n unbindOutside?.()\r\n unbindOutside = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n const toggleListener = (): void => (isOpen ? close() : open())\r\n input.addEventListener('click', toggleListener)\r\n calendarIcon.addEventListener('click', toggleListener)\r\n clearButton.addEventListener('click', (event) => {\r\n event.stopPropagation()\r\n value = undefined\r\n rangeAnchor = null\r\n input.value = ''\r\n syncClearButton()\r\n onChange?.(undefined)\r\n if (isOpen) renderCalendar()\r\n })\r\n const api: DatePickerApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n input.value = formatValue(newValue)\r\n syncClearButton()\r\n },\r\n open,\r\n close,\r\n isOpen() {\r\n return isOpen\r\n },\r\n destroy() {\r\n input.removeEventListener('click', toggleListener)\r\n calendarIcon.removeEventListener('click', toggleListener)\r\n unbindOutside?.()\r\n unbindEscape?.()\r\n calendar.removeEventListener('keydown', handleKeydown)\r\n calendar.remove()\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Options accepted by the `FileDropzone` factory. */\r\nexport interface FileDropzoneOptions {\r\n /** Label text shown inside the drop area. Defaults to `'Drop files here or click to browse'`. */\r\n label?: string\r\n /** Comma-separated MIME types/extensions passed to the underlying file input. */\r\n accept?: string\r\n /** Allows selecting multiple files. Defaults to `false`. */\r\n multiple?: boolean\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called with the selected/dropped files. */\r\n onFiles: (files: File[]) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `FileDropzone` element. */\r\nexport interface FileDropzoneApi {\r\n /** Clears the underlying file input's selection. */\r\n reset: () => void\r\n /** Detaches the dropzone from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `FileDropzone` is a real `HTMLDivElement` extended with `FileDropzoneApi`. */\r\nexport type FileDropzoneElement = HTMLDivElement & FileDropzoneApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const dropzoneCss = `\r\n.linteau-dropzone { border: 1px dashed var(--linteau-border); border-radius: var(--linteau-radius-lg); padding: 24px; display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; cursor: pointer; color: var(--linteau-muted-foreground); transition: border-color 120ms ease, background 120ms ease }\r\n.linteau-dropzone:hover, .linteau-dropzone-active { border-color: var(--linteau-ring); background: var(--linteau-accent) }\r\n.linteau-dropzone-disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-dropzone-label { font-size: 12px }\r\n`\r\n\r\n/** Creates a drag-and-drop file upload zone with a click-to-browse fallback. */\r\nexport function FileDropzone(options: FileDropzoneOptions): FileDropzoneElement {\r\n assertDom('FileDropzone')\r\n ensureComponentStyles('dropzone', dropzoneCss)\r\n const disabled = options.disabled ?? false\r\n const root = el('div', cx(px('dropzone'), disabled && px('dropzone-disabled')))\r\n const icon = Icon(icons.upload, 22, { className: px('icon') })\r\n if (icon) root.appendChild(icon)\r\n const label = el('div', px('dropzone-label'))\r\n label.textContent = options.label ?? 'Drop files here or click to browse'\r\n root.appendChild(label)\r\n const input = document.createElement('input')\r\n input.type = 'file'\r\n input.style.display = 'none'\r\n input.multiple = options.multiple ?? false\r\n if (options.accept) input.accept = options.accept\r\n input.disabled = disabled\r\n function emit(fileList: FileList | null): void {\r\n if (!fileList || fileList.length === 0) return\r\n options.onFiles(Array.from(fileList))\r\n }\r\n const clickListener = (): void => { if (!disabled) input.click() }\r\n const changeListener = (): void => emit(input.files)\r\n const dragOverListener = (event: DragEvent): void => {\r\n event.preventDefault()\r\n if (!disabled) root.classList.add(px('dropzone-active'))\r\n }\r\n const dragLeaveListener = (): void => root.classList.remove(px('dropzone-active'))\r\n const dropListener = (event: DragEvent): void => {\r\n event.preventDefault()\r\n root.classList.remove(px('dropzone-active'))\r\n if (!disabled) emit(event.dataTransfer?.files ?? null)\r\n }\r\n root.addEventListener('click', clickListener)\r\n root.addEventListener('dragover', dragOverListener)\r\n root.addEventListener('dragleave', dragLeaveListener)\r\n root.addEventListener('drop', dropListener)\r\n input.addEventListener('change', changeListener)\r\n root.appendChild(input)\r\n const api: FileDropzoneApi = {\r\n reset() {\r\n input.value = ''\r\n },\r\n destroy() {\r\n root.removeEventListener('click', clickListener)\r\n root.removeEventListener('dragover', dragOverListener)\r\n root.removeEventListener('dragleave', dragLeaveListener)\r\n root.removeEventListener('drop', dropListener)\r\n input.removeEventListener('change', changeListener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** Options accepted by the `Card` factory. All slots are optional. */\r\nexport interface CardOptions {\r\n /** Content rendered in the header slot (a border-separated top strip). */\r\n header?: HTMLElement | string\r\n /** Content rendered in the footer slot (a border-separated bottom strip). */\r\n footer?: HTMLElement | string\r\n}\r\n\r\n/** The runtime control surface attached to every `Card` element. */\r\nexport interface CardApi {\r\n /** The main content container -- append anything here. */\r\n body: HTMLElement\r\n /** Replaces the header slot content (pass `null` to remove it). */\r\n setHeader: (content: HTMLElement | string | null) => void\r\n /** Replaces the footer slot content (pass `null` to remove it). */\r\n setFooter: (content: HTMLElement | string | null) => void\r\n /** Detaches the card from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Card` is a real `HTMLDivElement` extended with `CardApi`. */\r\nexport type CardElement = HTMLDivElement & CardApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const cardCss = `\r\n.linteau-card { border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); background: var(--linteau-card); color: var(--linteau-card-foreground); overflow: hidden }\r\n.linteau-card-header { padding: 14px 16px; border-bottom: 1px solid var(--linteau-border); font-weight: 600 }\r\n.linteau-card-body { padding: 16px }\r\n.linteau-card-footer { padding: 12px 16px; border-top: 1px solid var(--linteau-border) }\r\n`\r\n\r\n/** Creates a bordered, sectioned surface with optional header/footer slots and a body you fill freely. */\r\nexport function Card(options: CardOptions = {}): CardElement {\r\n assertDom('Card')\r\n ensureComponentStyles('card', cardCss)\r\n const root = el('div', px('card'))\r\n const headerEl = el('div', px('card-header'))\r\n const body = el('div', px('card-body'))\r\n const footerEl = el('div', px('card-footer'))\r\n function fill(target: HTMLElement, content: HTMLElement | string | null): void {\r\n target.replaceChildren()\r\n if (content instanceof HTMLElement) target.appendChild(content)\r\n else if (typeof content === 'string') target.textContent = content\r\n }\r\n function syncVisibility(target: HTMLElement, content: HTMLElement | string | null): void {\r\n target.style.display = content == null ? 'none' : ''\r\n }\r\n fill(headerEl, options.header ?? null)\r\n fill(footerEl, options.footer ?? null)\r\n syncVisibility(headerEl, options.header ?? null)\r\n syncVisibility(footerEl, options.footer ?? null)\r\n root.append(headerEl, body, footerEl)\r\n const api: CardApi = {\r\n body,\r\n setHeader(content) {\r\n fill(headerEl, content)\r\n syncVisibility(headerEl, content)\r\n },\r\n setFooter(content) {\r\n fill(footerEl, content)\r\n syncVisibility(footerEl, content)\r\n },\r\n destroy() {\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","// components/layout/Section.ts\r\nimport { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Options accepted by the `Section` factory. */\r\nexport interface SectionOptions {\r\n /** Optional icon rendered before the title. */\r\n icon?: IconInput\r\n /** When `true`, the header becomes clickable and toggles the body. Defaults to `false`. */\r\n collapsible?: boolean\r\n /** Initial collapsed state when `collapsible` is `true`. Defaults to `false`. */\r\n defaultCollapsed?: boolean\r\n /** Extra elements (e.g. buttons) rendered on the right side of the header. */\r\n actions?: HTMLElement[]\r\n}\r\n\r\n/** The runtime control surface attached to every `Section` element. */\r\nexport interface SectionApi {\r\n /** The header element, exposed for advanced customization. */\r\n header: HTMLElement\r\n /** The body container -- append your fields/content here. */\r\n body: HTMLElement\r\n /** Updates the section title text. */\r\n setTitle: (title: string) => void\r\n /** Programmatically collapses/expands the section (only relevant when `collapsible`). */\r\n setCollapsed: (collapsed: boolean) => void\r\n /** Returns whether the section is currently collapsed. */\r\n isCollapsed: () => boolean\r\n /** Detaches the section from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Section` is a real `HTMLDivElement` extended with `SectionApi`. */\r\nexport type SectionElement = HTMLDivElement & SectionApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const sectionCss = `\r\n.linteau-section { border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); background: var(--linteau-muted); overflow: hidden; width: 100% }\r\n.linteau-section-header { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--linteau-border); color: var(--linteau-muted-foreground); cursor: default }\r\n.linteau-section-header.linteau-section-collapsible { cursor: pointer }\r\n.linteau-section-header h3 { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; flex: 1 }\r\n.linteau-section-actions { display: flex; align-items: center; gap: 6px }\r\n.linteau-section-body { padding: 12px; display: flex; flex-direction: column; gap: 12px }\r\n.linteau-section-body.linteau-collapsed { display: none }\r\n.linteau-section-chevron { transition: transform 150ms ease }\r\n.linteau-section-chevron.linteau-collapsed { transform: rotate(-90deg) }\r\n`\r\n\r\n/** Creates a titled, bordered container -- the primary layout grouping primitive of the library. */\r\nexport function Section(title: string, options: SectionOptions = {}): SectionElement {\r\n assertDom('Section')\r\n ensureComponentStyles('section', sectionCss)\r\n const { icon, collapsible = false, defaultCollapsed = false, actions = [] } = options\r\n let collapsed = defaultCollapsed\r\n const root = el('div', px('section'))\r\n const header = el('div', cx(px('section-header'), collapsible && px('section-collapsible')))\r\n const titleEl = document.createElement('h3')\r\n titleEl.textContent = title\r\n const body = el('div', cx(px('section-body'), collapsed && px('collapsed')))\r\n const headerIcon = icon ? Icon(icon, 14, { className: px('icon') }) : null\r\n const chevron = collapsible ? Icon(icons.chevronDown, 14, { className: cx(px('icon'), px('section-chevron'), collapsed && px('collapsed')) }) : null\r\n const actionsWrap = el('div', px('section-actions'))\r\n actionsWrap.append(...actions)\r\n if (headerIcon) header.appendChild(headerIcon)\r\n header.appendChild(titleEl)\r\n if (actions.length) header.appendChild(actionsWrap)\r\n if (chevron) header.appendChild(chevron)\r\n root.append(header, body)\r\n function applyCollapsed(): void {\r\n body.classList.toggle(px('collapsed'), collapsed)\r\n chevron?.classList.toggle(px('collapsed'), collapsed)\r\n }\r\n const clickListener = (): void => {\r\n collapsed = !collapsed\r\n applyCollapsed()\r\n }\r\n if (collapsible) header.addEventListener('click', clickListener)\r\n const api: SectionApi = {\r\n header,\r\n body,\r\n setTitle(newTitle) {\r\n titleEl.textContent = newTitle\r\n },\r\n setCollapsed(value) {\r\n collapsed = value\r\n applyCollapsed()\r\n },\r\n isCollapsed() {\r\n return collapsed\r\n },\r\n destroy() {\r\n if (collapsible) header.removeEventListener('click', clickListener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** Options accepted by the `Separator` factory. */\r\nexport interface SeparatorOptions {\r\n /** Layout direction. Defaults to `'horizontal'`. */\r\n orientation?: 'horizontal' | 'vertical'\r\n}\r\n\r\n/** The runtime control surface attached to every `Separator` element. */\r\nexport interface SeparatorApi {\r\n /** Switches orientation, updating classes in place. */\r\n setOrientation: (orientation: 'horizontal' | 'vertical') => void\r\n /** Detaches the separator from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Separator` is a real `HTMLHRElement` extended with `SeparatorApi`. */\r\nexport type SeparatorElement = HTMLHRElement & SeparatorApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const separatorCss = `\r\n.linteau-separator { background: var(--linteau-border); border: none; flex-shrink: 0 }\r\n.linteau-separator-horizontal { width: 100%; height: 1px }\r\n.linteau-separator-vertical { width: 1px; height: 100% }\r\n`\r\n\r\n/** Creates a thin dividing line, horizontal or vertical. */\r\nexport function Separator(options: SeparatorOptions = {}): SeparatorElement {\r\n assertDom('Separator')\r\n ensureComponentStyles('separator', separatorCss)\r\n let orientation = options.orientation ?? 'horizontal'\r\n const hr = el('hr', cx(px('separator'), px(`separator-${orientation}`)))\r\n hr.setAttribute('role', 'separator')\r\n const api: SeparatorApi = {\r\n setOrientation(newOrientation) {\r\n hr.classList.remove(px(`separator-${orientation}`))\r\n orientation = newOrientation\r\n hr.classList.add(px(`separator-${orientation}`))\r\n },\r\n destroy() {\r\n hr.remove()\r\n }\r\n }\r\n return attachController(hr, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Options accepted by the `ModeCard` factory. */\r\nexport interface ModeCardOptions {\r\n /** Title text. */\r\n label: string\r\n /** Description text, hidden and replaced by a lock message when `locked` is `true`. */\r\n description: string\r\n /** Icon shown at the top of the card (replaced by a lock icon when `locked`). */\r\n icon: IconInput\r\n /** Disables selection and shows a lock icon/message. Defaults to `false`. */\r\n locked?: boolean\r\n /** Message shown instead of `description` when locked. Defaults to `'Coming in the next update'`. */\r\n lockedMessage?: string\r\n /** Initial selected visual state. Defaults to `false`. */\r\n selected?: boolean\r\n /** Called when the (unlocked) card is clicked. */\r\n onSelect?: () => void\r\n}\r\n\r\n/** The runtime control surface attached to every `ModeCard` element. */\r\nexport interface ModeCardApi {\r\n /** Returns whether the card is currently marked as selected. */\r\n isSelected: () => boolean\r\n /** Programmatically toggles the selected visual state. */\r\n setSelected: (selected: boolean) => void\r\n /** Programmatically locks/unlocks the card. */\r\n setLocked: (locked: boolean) => void\r\n /** Detaches the card from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ModeCard` is a real `HTMLButtonElement` extended with `ModeCardApi`. */\r\nexport type ModeCardElement = HTMLButtonElement & ModeCardApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const modeCardCss = `\r\n.linteau-mode-card { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 14px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); color: var(--linteau-foreground); cursor: pointer; text-align: left; font-family: inherit; transition: border-color 120ms ease, transform 120ms ease }\r\n.linteau-mode-card:hover:not(.linteau-locked) { border-color: var(--linteau-ring); transform: translateY(-2px) }\r\n.linteau-mode-card.linteau-selected { border-color: var(--linteau-primary); box-shadow: 0 0 0 1px var(--linteau-primary) }\r\n.linteau-mode-card.linteau-locked { opacity: 0.45; cursor: not-allowed }\r\n.linteau-mode-card-icon { color: var(--linteau-foreground) }\r\n.linteau-mode-card-title { font-weight: 600; font-size: 13px }\r\n.linteau-mode-card-description { font-size: 11px; color: var(--linteau-muted-foreground) }\r\n`\r\n\r\n/** Creates a selectable, optionally lockable option card -- typically used in mode/menu pickers. */\r\nexport function ModeCard(options: ModeCardOptions): ModeCardElement {\r\n assertDom('ModeCard')\r\n ensureComponentStyles('mode-card', modeCardCss)\r\n let locked = options.locked ?? false\r\n let selected = options.selected ?? false\r\n const lockedMessage = options.lockedMessage ?? 'Coming in the next update'\r\n const root = el('button', px('mode-card'))\r\n root.type = 'button'\r\n const iconWrap = el('div', px('mode-card-icon'))\r\n const textWrap = el('div', px('mode-card-text'))\r\n const titleEl = el('div', px('mode-card-title'))\r\n titleEl.textContent = options.label\r\n const descEl = el('div', px('mode-card-description'))\r\n textWrap.append(titleEl, descEl)\r\n function render(): void {\r\n iconWrap.replaceChildren()\r\n const iconEl = Icon(locked ? icons.lock : options.icon, 20, { className: px('icon') })\r\n if (iconEl) iconWrap.appendChild(iconEl)\r\n descEl.textContent = locked ? lockedMessage : options.description\r\n root.classList.toggle(px('locked'), locked)\r\n root.classList.toggle(px('selected'), selected)\r\n root.disabled = locked\r\n }\r\n render()\r\n root.append(iconWrap, textWrap)\r\n const listener = (): void => {\r\n if (locked) return\r\n options.onSelect?.()\r\n }\r\n root.addEventListener('click', listener)\r\n const api: ModeCardApi = {\r\n isSelected() {\r\n return selected\r\n },\r\n setSelected(value) {\r\n selected = value\r\n render()\r\n },\r\n setLocked(value) {\r\n locked = value\r\n render()\r\n },\r\n destroy() {\r\n root.removeEventListener('click', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single collapsible section within an `Accordion`. */\r\nexport interface AccordionItem {\r\n /** Visible header label. */\r\n label: string\r\n /** Unique value identifying this section. */\r\n value: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Content revealed when this section is open. */\r\n content: HTMLElement\r\n}\r\n\r\n/** Options accepted by the `Accordion` factory. */\r\nexport interface AccordionOptions {\r\n /** The sections to render. */\r\n items: AccordionItem[]\r\n /** Allows more than one section open at once. Defaults to `false`. */\r\n multiple?: boolean\r\n /** Values open by default. */\r\n defaultOpen?: string[]\r\n /** Called whenever the set of open sections changes. */\r\n onChange?: (openValues: string[]) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Accordion` element. */\r\nexport interface AccordionApi {\r\n /** Returns the values of currently open sections. */\r\n getOpen: () => string[]\r\n /** Opens a section by value. */\r\n open: (value: string) => void\r\n /** Closes a section by value. */\r\n close: (value: string) => void\r\n /** Toggles a section by value. */\r\n toggle: (value: string) => void\r\n /** Detaches the accordion from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** An `Accordion` is a real `HTMLDivElement` extended with `AccordionApi`. */\r\nexport type AccordionElement = HTMLDivElement & AccordionApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const accordionCss = `\r\n.linteau-accordion { display: flex; flex-direction: column; gap: 8px; width: 100% }\r\n.linteau-accordion-item { border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); overflow: hidden }\r\n.linteau-accordion-header { display: flex; align-items: center; gap: 8px; width: 100%; padding: 12px; background: var(--linteau-muted); border: none; cursor: pointer; font-size: 13px; font-weight: 500; color: var(--linteau-foreground); font-family: inherit }\r\n.linteau-accordion-chevron { margin-left: auto; transition: transform 150ms ease }\r\n.linteau-accordion-chevron.linteau-open { transform: rotate(180deg) }\r\n.linteau-accordion-content { padding: 12px }\r\n.linteau-accordion-content.linteau-collapsed { display: none }\r\n`\r\n\r\n/** Creates a set of collapsible sections, single- or multi-open. */\r\nexport function Accordion(options: AccordionOptions): AccordionElement {\r\n assertDom('Accordion')\r\n ensureComponentStyles('accordion', accordionCss)\r\n const multiple = options.multiple ?? false\r\n let openValues = new Set(options.defaultOpen ?? [])\r\n const onChange = options.onChange\r\n const cleanupListeners: Array<() => void> = []\r\n const root = el('div', px('accordion'))\r\n function setOpenState(value: string, shouldOpen: boolean): void {\r\n if (shouldOpen) {\r\n if (!multiple) openValues.clear()\r\n openValues.add(value)\r\n } else {\r\n openValues.delete(value)\r\n }\r\n render()\r\n onChange?.(Array.from(openValues))\r\n }\r\n function render(): void {\r\n root.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n for (const item of options.items) {\r\n const isOpen = openValues.has(item.value)\r\n const itemEl = el('div', px('accordion-item'))\r\n const header = el('button', px('accordion-header'))\r\n header.type = 'button'\r\n if (item.icon) header.appendChild(Icon(item.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = item.label\r\n const chevron = Icon(icons.chevronDown, 14, { className: cx(px('accordion-chevron'), isOpen && px('open')) })!\r\n header.append(label, chevron)\r\n const content = el('div', cx(px('accordion-content'), !isOpen && px('collapsed')))\r\n content.appendChild(item.content)\r\n const listener = (): void => setOpenState(item.value, !isOpen)\r\n header.addEventListener('click', listener)\r\n cleanupListeners.push(() => header.removeEventListener('click', listener))\r\n itemEl.append(header, content)\r\n root.appendChild(itemEl)\r\n }\r\n }\r\n render()\r\n const api: AccordionApi = {\r\n getOpen() {\r\n return Array.from(openValues)\r\n },\r\n open(value) {\r\n setOpenState(value, true)\r\n },\r\n close(value) {\r\n setOpenState(value, false)\r\n },\r\n toggle(value) {\r\n setOpenState(value, !openValues.has(value))\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** A single crumb in a `Breadcrumb`. The last item in the list is rendered as the non-interactive current page. */\r\nexport interface BreadcrumbItem {\r\n /** Visible label. */\r\n label: string\r\n /** Called when the crumb is clicked (ignored for the last/current item). */\r\n onClick?: () => void\r\n}\r\n\r\n/** Options accepted by the `Breadcrumb` factory. */\r\nexport interface BreadcrumbOptions {\r\n /** The trail of crumbs, in order from root to current page. */\r\n items: BreadcrumbItem[]\r\n}\r\n\r\n/** The runtime control surface attached to every `Breadcrumb` element. */\r\nexport interface BreadcrumbApi {\r\n /** Replaces the full trail. */\r\n setItems: (items: BreadcrumbItem[]) => void\r\n /** Detaches the breadcrumb from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Breadcrumb` is a real `HTMLElement` (`<nav>`) extended with `BreadcrumbApi`. */\r\nexport type BreadcrumbElement = HTMLElement & BreadcrumbApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const breadcrumbCss = `\r\n.linteau-breadcrumb { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--linteau-muted-foreground) }\r\n.linteau-breadcrumb-item { background: transparent; border: none; color: var(--linteau-muted-foreground); cursor: pointer; font: inherit; padding: 0 }\r\n.linteau-breadcrumb-item:hover { color: var(--linteau-foreground) }\r\n.linteau-breadcrumb-current { color: var(--linteau-foreground); font-weight: 500 }\r\n`\r\n\r\n/** Creates a navigational trail of crumbs separated by chevrons. */\r\nexport function Breadcrumb(options: BreadcrumbOptions): BreadcrumbElement {\r\n assertDom('Breadcrumb')\r\n ensureComponentStyles('breadcrumb', breadcrumbCss)\r\n const nav = el('nav', px('breadcrumb'))\r\n nav.setAttribute('aria-label', 'breadcrumb')\r\n const cleanupListeners: Array<() => void> = []\r\n function render(items: BreadcrumbItem[]): void {\r\n nav.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n items.forEach((item, index) => {\r\n const isLast = index === items.length - 1\r\n if (isLast) {\r\n const current = el('span', px('breadcrumb-current'))\r\n current.textContent = item.label\r\n nav.appendChild(current)\r\n } else {\r\n const button = el('button', px('breadcrumb-item'))\r\n button.type = 'button'\r\n button.textContent = item.label\r\n const listener = (): void => item.onClick?.()\r\n button.addEventListener('click', listener)\r\n cleanupListeners.push(() => button.removeEventListener('click', listener))\r\n nav.appendChild(button)\r\n const separator = Icon(icons.chevronRight, 12, { className: px('icon') })\r\n if (separator) nav.appendChild(separator)\r\n }\r\n })\r\n }\r\n render(options.items)\r\n const api: BreadcrumbApi = {\r\n setItems(items) {\r\n render(items)\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n nav.remove()\r\n }\r\n }\r\n return attachController(nav, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Options accepted by the `Pagination` factory. */\r\nexport interface PaginationOptions {\r\n /** Controlled current page (1-indexed). */\r\n page?: number\r\n /** Uncontrolled initial page, used only if `page` is omitted. Defaults to `1`. */\r\n defaultPage?: number\r\n /** Total number of pages. */\r\n pageCount: number\r\n /** Page buttons shown on each side of the current page before collapsing into an ellipsis. Defaults to `1`. */\r\n siblingCount?: number\r\n /** Called whenever the user navigates to a new page. */\r\n onChange?: (page: number) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Pagination` element. */\r\nexport interface PaginationApi {\r\n /** Returns the current page. */\r\n getPage: () => number\r\n /** Programmatically navigates to a page (does not trigger `onChange`). */\r\n setPage: (page: number) => void\r\n /** Updates the total page count and re-renders. */\r\n setPageCount: (pageCount: number) => void\r\n /** Detaches the control from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Pagination` is a real `HTMLDivElement` extended with `PaginationApi`. */\r\nexport type PaginationElement = HTMLDivElement & PaginationApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const paginationCss = `\r\n.linteau-pagination { display: flex; align-items: center; gap: 4px }\r\n.linteau-pagination-item { min-width: 28px; height: 28px; padding: 0 6px; display: flex; align-items: center; justify-content: center; border-radius: var(--linteau-radius-sm); border: 1px solid transparent; background: transparent; color: var(--linteau-muted-foreground); font-size: 12px; cursor: pointer; font-family: inherit }\r\n.linteau-pagination-item:hover:not(:disabled) { background: var(--linteau-accent) }\r\n.linteau-pagination-item:disabled { opacity: 0.4; cursor: not-allowed }\r\n.linteau-pagination-item-active { background: var(--linteau-primary); color: var(--linteau-primary-foreground) }\r\n.linteau-pagination-ellipsis { color: var(--linteau-muted-foreground); padding: 0 4px }\r\n`\r\n\r\nfunction buildRange(current: number, pageCount: number, siblingCount: number): Array<number | 'ellipsis'> {\r\n const totalVisible = siblingCount * 2 + 5\r\n if (pageCount <= totalVisible) return Array.from({ length: pageCount }, (_, i) => i + 1)\r\n const leftSibling = Math.max(current - siblingCount, 1)\r\n const rightSibling = Math.min(current + siblingCount, pageCount)\r\n const showLeftEllipsis = leftSibling > 2\r\n const showRightEllipsis = rightSibling < pageCount - 1\r\n const range: Array<number | 'ellipsis'> = [1]\r\n if (showLeftEllipsis) range.push('ellipsis')\r\n for (let page = Math.max(leftSibling, 2); page <= Math.min(rightSibling, pageCount - 1); page++) range.push(page)\r\n if (showRightEllipsis) range.push('ellipsis')\r\n if (pageCount > 1) range.push(pageCount)\r\n return range\r\n}\r\n\r\n/** Creates a page-number navigator with previous/next controls and smart ellipsis collapsing. */\r\nexport function Pagination(options: PaginationOptions): PaginationElement {\r\n assertDom('Pagination')\r\n ensureComponentStyles('pagination', paginationCss)\r\n let page = options.page ?? options.defaultPage ?? 1\r\n let pageCount = options.pageCount\r\n const siblingCount = options.siblingCount ?? 1\r\n const onChange = options.onChange\r\n const cleanupListeners: Array<() => void> = []\r\n const root = el('div', px('pagination'))\r\n root.setAttribute('role', 'navigation')\r\n function goTo(newPage: number): void {\r\n page = Math.max(1, Math.min(pageCount, newPage))\r\n render()\r\n onChange?.(page)\r\n }\r\n function render(): void {\r\n root.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n const prev = el('button', px('pagination-item'))\r\n prev.type = 'button'\r\n const prevIcon = Icon(icons.chevronLeft, 14)\r\n if (prevIcon) prev.appendChild(prevIcon)\r\n prev.disabled = page <= 1\r\n const prevListener = (): void => goTo(page - 1)\r\n prev.addEventListener('click', prevListener)\r\n cleanupListeners.push(() => prev.removeEventListener('click', prevListener))\r\n root.appendChild(prev)\r\n for (const entry of buildRange(page, pageCount, siblingCount)) {\r\n if (entry === 'ellipsis') {\r\n root.appendChild(el('span', px('pagination-ellipsis')))\r\n continue\r\n }\r\n const button = el('button', cx(px('pagination-item'), entry === page && px('pagination-item-active')))\r\n button.type = 'button'\r\n button.textContent = String(entry)\r\n const listener = (): void => goTo(entry)\r\n button.addEventListener('click', listener)\r\n cleanupListeners.push(() => button.removeEventListener('click', listener))\r\n root.appendChild(button)\r\n }\r\n const next = el('button', px('pagination-item'))\r\n next.type = 'button'\r\n const nextIcon = Icon(icons.chevronRight, 14)\r\n if (nextIcon) next.appendChild(nextIcon)\r\n next.disabled = page >= pageCount\r\n const nextListener = (): void => goTo(page + 1)\r\n next.addEventListener('click', nextListener)\r\n cleanupListeners.push(() => next.removeEventListener('click', nextListener))\r\n root.appendChild(next)\r\n }\r\n render()\r\n const api: PaginationApi = {\r\n getPage() {\r\n return page\r\n },\r\n setPage(newPage) {\r\n page = Math.max(1, Math.min(pageCount, newPage))\r\n render()\r\n },\r\n setPageCount(newPageCount) {\r\n pageCount = newPageCount\r\n render()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single tab: its trigger label/icon and the panel content it reveals. */\r\nexport interface TabItem {\r\n /** Visible trigger label. */\r\n label: string\r\n /** Unique value identifying this tab. */\r\n value: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Content shown in the panel while this tab is active. */\r\n content: HTMLElement\r\n}\r\n\r\n/** Options accepted by the `Tabs` factory. */\r\nexport interface TabsOptions {\r\n /** The tabs to render. */\r\n items: TabItem[]\r\n /** Controlled active value. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. Defaults to the first item. */\r\n defaultValue?: string\r\n /** Called whenever the active tab changes. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Tabs` element. */\r\nexport interface TabsApi {\r\n /** Returns the currently active tab's value. */\r\n getValue: () => string\r\n /** Programmatically activates a tab (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Detaches the tabs from the DOM and their internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Tabs` is a real `HTMLDivElement` extended with `TabsApi`. */\r\nexport type TabsElement = HTMLDivElement & TabsApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const tabsCss = `\r\n.linteau-tabs { display: flex; flex-direction: column; gap: 12px; width: 100% }\r\n.linteau-tabs-list { display: flex; gap: 4px; border-bottom: 1px solid var(--linteau-border) }\r\n.linteau-tabs-trigger { background: transparent; border: none; border-bottom: 2px solid transparent; padding: 8px 12px; font-size: 12px; font-weight: 500; color: var(--linteau-muted-foreground); cursor: pointer; display: flex; align-items: center; gap: 6px; font-family: inherit }\r\n.linteau-tabs-trigger:hover { color: var(--linteau-foreground) }\r\n.linteau-tabs-trigger-active { color: var(--linteau-foreground); border-bottom-color: var(--linteau-primary) }\r\n.linteau-tabs-panel { width: 100% }\r\n`\r\n\r\n/** Creates a tabbed container: a trigger list plus a panel that swaps content per active tab. */\r\nexport function Tabs(options: TabsOptions): TabsElement {\r\n assertDom('Tabs')\r\n ensureComponentStyles('tabs', tabsCss)\r\n let value = options.value ?? options.defaultValue ?? options.items[0]?.value ?? ''\r\n const onChange = options.onChange\r\n const cleanupListeners: Array<() => void> = []\r\n const root = el('div', px('tabs'))\r\n const list = el('div', px('tabs-list'))\r\n list.setAttribute('role', 'tablist')\r\n const panel = el('div', px('tabs-panel'))\r\n function renderPanel(): void {\r\n const active = options.items.find((item) => item.value === value)\r\n panel.replaceChildren()\r\n if (active) panel.appendChild(active.content)\r\n }\r\n function renderTriggers(): void {\r\n list.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n for (const item of options.items) {\r\n const trigger = el('button', cx(px('tabs-trigger'), item.value === value && px('tabs-trigger-active')))\r\n trigger.type = 'button'\r\n trigger.setAttribute('role', 'tab')\r\n if (item.icon) trigger.appendChild(Icon(item.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = item.label\r\n trigger.appendChild(label)\r\n const listener = (): void => {\r\n value = item.value\r\n renderTriggers()\r\n renderPanel()\r\n onChange?.(value)\r\n }\r\n trigger.addEventListener('click', listener)\r\n cleanupListeners.push(() => trigger.removeEventListener('click', listener))\r\n list.appendChild(trigger)\r\n }\r\n }\r\n renderTriggers()\r\n renderPanel()\r\n root.append(list, panel)\r\n const api: TabsApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n renderTriggers()\r\n renderPanel()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onEscapeKey, lockBodyScroll } from '../../core/overlay'\r\nimport { fillContent } from '../../core/content'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Options accepted by the `Dialog` factory. */\r\nexport interface DialogOptions {\r\n /** Title shown in the header. */\r\n title?: string\r\n /** Initial body content. */\r\n content?: HTMLElement | string\r\n /** Footer action elements (e.g. Buttons), right-aligned. */\r\n actions?: HTMLElement[]\r\n /** Closes the dialog when the backdrop is clicked. Defaults to `true`. */\r\n closeOnBackdrop?: boolean\r\n /** Closes the dialog on Escape. Defaults to `true`. */\r\n closeOnEscape?: boolean\r\n /** Called whenever the open state changes. */\r\n onOpenChange?: (open: boolean) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Dialog` element. */\r\nexport interface DialogApi {\r\n /** The scrollable body container -- set once via `content`, or update later with `setContent`. */\r\n body: HTMLElement\r\n /** Opens the dialog: locks scroll, binds Escape. */\r\n open: () => void\r\n /** Closes the dialog. */\r\n close: () => void\r\n /** Returns whether the dialog is currently open. */\r\n isOpen: () => boolean\r\n /** Updates the header title text. */\r\n setTitle: (title: string) => void\r\n /** Replaces the body content. */\r\n setContent: (content: HTMLElement | string) => void\r\n /** Removes all listeners/subscriptions and detaches the dialog from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Dialog` is a real `HTMLDivElement` (the overlay) extended with `DialogApi`. */\r\nexport type DialogElement = HTMLDivElement & DialogApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const dialogCss = `\r\n.linteau-dialog-overlay { position: fixed; inset: 0; background: color-mix(in oklch, black 60%, transparent); display: flex; align-items: center; justify-content: center; z-index: 1000; backdrop-filter: blur(4px) }\r\n.linteau-dialog-panel { width: min(480px, 92vw); max-height: 86vh; display: flex; flex-direction: column; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-lg); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); overflow: hidden }\r\n.linteau-dialog-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid var(--linteau-border) }\r\n.linteau-dialog-title { font-size: 14px; font-weight: 600 }\r\n.linteau-dialog-close { background: transparent; border: none; color: var(--linteau-muted-foreground); cursor: pointer; display: flex; padding: 4px; border-radius: var(--linteau-radius-sm) }\r\n.linteau-dialog-close:hover { background: var(--linteau-accent); color: var(--linteau-foreground) }\r\n.linteau-dialog-body { padding: 16px; overflow-y: auto }\r\n.linteau-dialog-footer { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--linteau-border) }\r\n`\r\n\r\n/** Creates a centered modal dialog with a backdrop, focus-safe scroll lock, and Escape-to-close. */\r\nexport function Dialog(options: DialogOptions = {}): DialogElement {\r\n assertDom('Dialog')\r\n ensureComponentStyles('dialog', dialogCss)\r\n const closeOnBackdrop = options.closeOnBackdrop ?? true\r\n const closeOnEscape = options.closeOnEscape ?? true\r\n let isOpen = false\r\n let unlockScroll: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const overlay = el('div', cx(px('dialog-overlay'), px('hidden')))\r\n const panel = el('div', px('dialog-panel'))\r\n panel.setAttribute('role', 'dialog')\r\n panel.setAttribute('aria-modal', 'true')\r\n const header = el('div', px('dialog-header'))\r\n const titleEl = el('div', px('dialog-title'))\r\n titleEl.textContent = options.title ?? ''\r\n const closeButton = el('button', px('dialog-close'))\r\n closeButton.type = 'button'\r\n const closeIcon = Icon(icons.x, 16)\r\n if (closeIcon) closeButton.appendChild(closeIcon)\r\n header.append(titleEl, closeButton)\r\n const body = el('div', px('dialog-body'))\r\n if (options.content) fillContent(body, options.content)\r\n const footer = el('div', px('dialog-footer'))\r\n if (options.actions?.length) footer.append(...options.actions)\r\n panel.append(header, body)\r\n if (options.actions?.length) panel.appendChild(footer)\r\n overlay.appendChild(panel)\r\n function setOpen(value: boolean): void {\r\n isOpen = value\r\n overlay.classList.toggle(px('hidden'), !value)\r\n if (value) {\r\n unlockScroll = lockBodyScroll()\r\n if (closeOnEscape) unbindEscape = onEscapeKey(close)\r\n } else {\r\n unlockScroll?.()\r\n unlockScroll = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n options.onOpenChange?.(value)\r\n }\r\n function close(): void {\r\n if (isOpen) setOpen(false)\r\n }\r\n const backdropListener = (event: MouseEvent): void => {\r\n if (closeOnBackdrop && event.target === overlay) close()\r\n }\r\n overlay.addEventListener('mousedown', backdropListener)\r\n closeButton.addEventListener('click', close)\r\n const api: DialogApi = {\r\n body,\r\n open() {\r\n setOpen(true)\r\n },\r\n close,\r\n isOpen() {\r\n return isOpen\r\n },\r\n setTitle(title) {\r\n titleEl.textContent = title\r\n },\r\n setContent(content) {\r\n fillContent(body, content)\r\n },\r\n destroy() {\r\n overlay.removeEventListener('mousedown', backdropListener)\r\n closeButton.removeEventListener('click', close)\r\n unlockScroll?.()\r\n unbindEscape?.()\r\n overlay.remove()\r\n }\r\n }\r\n return attachController(overlay, api)\r\n}","import { assertDom } from '../../core/dom'\r\nimport { Button } from '../button/Button'\r\nimport { Dialog } from './Dialog'\r\nimport type { Destroyable } from '../../core/types'\r\n\r\n/** Options accepted by the `AlertDialog` factory. */\r\nexport interface AlertDialogOptions {\r\n /** Title shown in the header. */\r\n title: string\r\n /** Supporting description text shown in the body. */\r\n description?: string\r\n /** Label for the dismiss action. Defaults to `'Cancel'`. */\r\n cancelText?: string\r\n /** Label for the confirm action. Defaults to `'Continue'`. */\r\n confirmText?: string\r\n /** Renders the confirm button in the destructive color -- use for irreversible actions. Defaults to `false`. */\r\n destructive?: boolean\r\n /** Called when the user confirms. */\r\n onConfirm?: () => void\r\n /** Called when the user cancels (via the Cancel button or Escape). */\r\n onCancel?: () => void\r\n}\r\n\r\n/**\r\n * The runtime control surface returned by `AlertDialog`. A thin wrapper over `Dialog` that\r\n * enforces the confirm-or-cancel pattern: unlike `Dialog`, clicking the backdrop never\r\n * dismisses it -- the user must explicitly choose.\r\n */\r\nexport interface AlertDialogApi extends Destroyable {\r\n /** Opens the alert dialog. */\r\n open: () => void\r\n /** Closes the alert dialog (equivalent to cancelling). */\r\n close: () => void\r\n /** Returns whether the alert dialog is currently open. */\r\n isOpen: () => boolean\r\n}\r\n\r\n/**\r\n * Creates a modal confirmation dialog for actions that need explicit user consent (deleting\r\n * a resource, discarding changes) -- built entirely on top of `Dialog` and `Button`, so it\r\n * ships no CSS of its own.\r\n */\r\nexport function AlertDialog(options: AlertDialogOptions): AlertDialogApi {\r\n assertDom('AlertDialog')\r\n let resolved = false\r\n const cancelButton = Button(options.cancelText ?? 'Cancel', {\r\n variant: 'outline',\r\n onClick: () => {\r\n resolved = true\r\n options.onCancel?.()\r\n dialog.close()\r\n }\r\n })\r\n const confirmButton = Button(options.confirmText ?? 'Continue', {\r\n variant: options.destructive ? 'destructive' : 'default',\r\n onClick: () => {\r\n resolved = true\r\n options.onConfirm?.()\r\n dialog.close()\r\n }\r\n })\r\n const dialog = Dialog({\r\n title: options.title,\r\n ...(options.description !== undefined ? { content: options.description } : {}),\r\n actions: [cancelButton, confirmButton],\r\n closeOnBackdrop: false,\r\n closeOnEscape: true,\r\n onOpenChange: (open) => {\r\n if (!open && !resolved) options.onCancel?.()\r\n resolved = false\r\n }\r\n })\r\n document.body.appendChild(dialog)\r\n return {\r\n open() {\r\n dialog.open()\r\n },\r\n close() {\r\n dialog.close()\r\n },\r\n isOpen() {\r\n return dialog.isOpen()\r\n },\r\n destroy() {\r\n dialog.destroy()\r\n }\r\n }\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onClickOutside, onEscapeKey, positionFloating } from '../../core/overlay'\r\nimport type { FloatingPlacement } from '../../core/overlay'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single actionable entry in a `DropdownMenu`/`ContextMenu`. */\r\nexport interface MenuItem {\r\n /** Visible label. */\r\n label: string\r\n /** Value passed to `onSelect` when this item is chosen. */\r\n value: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Disables this item. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Renders the item in the destructive color. Defaults to `false`. */\r\n destructive?: boolean\r\n}\r\n\r\n/** A visual divider between menu items. */\r\nexport interface MenuSeparator {\r\n separator: true\r\n}\r\n\r\n/** A single entry rendered by a menu -- either a selectable item or a separator. */\r\nexport type MenuEntry = MenuItem | MenuSeparator\r\n\r\nfunction isSeparator(entry: MenuEntry): entry is MenuSeparator {\r\n return 'separator' in entry\r\n}\r\n\r\n/** Renders `entries` into `container`, wiring up click handling. Shared by `DropdownMenu` and `ContextMenu`. */\r\nexport function renderMenuEntries(container: HTMLElement, entries: MenuEntry[], onSelect: (value: string) => void, onAfterSelect: () => void): void {\r\n container.replaceChildren()\r\n for (const entry of entries) {\r\n if (isSeparator(entry)) {\r\n container.appendChild(el('div', px('menu-separator')))\r\n continue\r\n }\r\n const item = el('div', cx(px('menu-item'), entry.disabled && px('menu-item-disabled'), entry.destructive && px('menu-item-destructive')))\r\n if (entry.icon) item.appendChild(Icon(entry.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = entry.label\r\n item.appendChild(label)\r\n item.addEventListener('click', () => {\r\n if (entry.disabled) return\r\n onSelect(entry.value)\r\n onAfterSelect()\r\n })\r\n container.appendChild(item)\r\n }\r\n}\r\n\r\n/** Options accepted by the `DropdownMenu` factory. */\r\nexport interface DropdownMenuOptions {\r\n /** The element the menu is anchored to and toggled by. */\r\n anchor: HTMLElement\r\n /** The menu's items/separators. */\r\n items: MenuEntry[]\r\n /** Side of the anchor the menu appears on. Defaults to `'bottom'`. */\r\n placement?: FloatingPlacement\r\n /** Called when an enabled item is chosen. */\r\n onSelect?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `DropdownMenu` element. */\r\nexport interface DropdownMenuApi {\r\n /** Opens the menu. */\r\n open: () => void\r\n /** Closes the menu. */\r\n close: () => void\r\n /** Toggles between open and closed. */\r\n toggle: () => void\r\n /** Returns whether the menu is currently open. */\r\n isOpen: () => boolean\r\n /** Replaces the full list of items/separators. */\r\n setItems: (items: MenuEntry[]) => void\r\n /** Removes all listeners and detaches the menu from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `DropdownMenu` is a real `HTMLDivElement` (the floating menu) extended with `DropdownMenuApi`. */\r\nexport type DropdownMenuElement = HTMLDivElement & DropdownMenuApi\r\n\r\n/** This component's own CSS. Reused by `ContextMenu` under the same `menu` key, so it's only ever injected once. */\r\nexport const menuCss = `\r\n.linteau-menu { position: fixed; z-index: 1200; min-width: 160px; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-md); padding: 4px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) }\r\n.linteau-menu-item { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: var(--linteau-radius-sm); font-size: 12px; color: var(--linteau-foreground); cursor: pointer }\r\n.linteau-menu-item:hover:not(.linteau-menu-item-disabled) { background: var(--linteau-accent) }\r\n.linteau-menu-item-disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-menu-item-destructive { color: var(--linteau-destructive) }\r\n.linteau-menu-separator { height: 1px; background: var(--linteau-border); margin: 4px 0 }\r\n`\r\n\r\n/** Creates a floating action menu anchored to another element, toggled by clicking that anchor. */\r\nexport function DropdownMenu(options: DropdownMenuOptions): DropdownMenuElement {\r\n assertDom('DropdownMenu')\r\n ensureComponentStyles('menu', menuCss)\r\n const { anchor, placement = 'bottom' } = options\r\n let items = options.items\r\n let isOpen = false\r\n let unbindOutside: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const menu = el('div', cx(px('menu'), px('hidden')))\r\n renderMenuEntries(menu, items, (value) => options.onSelect?.(value), close)\r\n function open(): void {\r\n if (isOpen) return\r\n isOpen = true\r\n document.body.appendChild(menu)\r\n menu.classList.remove(px('hidden'))\r\n positionFloating(anchor, menu, placement)\r\n unbindOutside = onClickOutside([anchor, menu], close)\r\n unbindEscape = onEscapeKey(close)\r\n }\r\n function close(): void {\r\n if (!isOpen) return\r\n isOpen = false\r\n menu.classList.add(px('hidden'))\r\n menu.remove()\r\n unbindOutside?.()\r\n unbindOutside = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n function toggle(): void {\r\n if (isOpen) close()\r\n else open()\r\n }\r\n const anchorListener = (): void => toggle()\r\n anchor.addEventListener('click', anchorListener)\r\n const api: DropdownMenuApi = {\r\n open,\r\n close,\r\n toggle,\r\n isOpen() {\r\n return isOpen\r\n },\r\n setItems(newItems) {\r\n items = newItems\r\n renderMenuEntries(menu, items, (value) => options.onSelect?.(value), close)\r\n },\r\n destroy() {\r\n anchor.removeEventListener('click', anchorListener)\r\n unbindOutside?.()\r\n unbindEscape?.()\r\n menu.remove()\r\n }\r\n }\r\n return attachController(menu, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onClickOutside, onEscapeKey } from '../../core/overlay'\r\nimport { renderMenuEntries, menuCss } from './DropdownMenu'\r\nimport type { MenuEntry } from './DropdownMenu'\r\nimport type { Destroyable } from '../../core/types'\r\n\r\n/** Options accepted by the `ContextMenu` factory. */\r\nexport interface ContextMenuOptions {\r\n /** The element that opens the menu on right-click. */\r\n target: HTMLElement\r\n /** The menu's items/separators. */\r\n items: MenuEntry[]\r\n /** Called when an enabled item is chosen. */\r\n onSelect?: (value: string) => void\r\n}\r\n\r\n/**\r\n * The runtime control surface returned by `ContextMenu`. This is a plain controller -- not\r\n * an element -- because it attaches behavior to an existing `target` rather than creating\r\n * a new one to place in your layout.\r\n */\r\nexport type ContextMenuApi = Destroyable\r\n\r\n/** Replaces the native right-click menu on `target` with a styled `ContextMenu`. Shares `.linteau-menu` CSS with `DropdownMenu` -- the `menu` key dedupes. */\r\nexport function ContextMenu(options: ContextMenuOptions): ContextMenuApi {\r\n assertDom('ContextMenu')\r\n ensureComponentStyles('menu', menuCss)\r\n const { target } = options\r\n let unbindOutside: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const menu = el('div', px('menu'))\r\n renderMenuEntries(menu, options.items, (value) => options.onSelect?.(value), close)\r\n menu.style.display = 'none'\r\n function close(): void {\r\n menu.style.display = 'none'\r\n menu.remove()\r\n unbindOutside?.()\r\n unbindOutside = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n const contextListener = (event: MouseEvent): void => {\r\n event.preventDefault()\r\n document.body.appendChild(menu)\r\n menu.style.display = 'block'\r\n menu.style.position = 'fixed'\r\n menu.style.top = `${event.clientY}px`\r\n menu.style.left = `${event.clientX}px`\r\n unbindOutside = onClickOutside(menu, close)\r\n unbindEscape = onEscapeKey(close)\r\n }\r\n target.addEventListener('contextmenu', contextListener)\r\n return {\r\n destroy() {\r\n target.removeEventListener('contextmenu', contextListener)\r\n unbindOutside?.()\r\n unbindEscape?.()\r\n menu.remove()\r\n }\r\n }\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onEscapeKey, lockBodyScroll } from '../../core/overlay'\r\nimport { fillContent } from '../../core/content'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\n\r\n/** Which edge of the screen a `Drawer` slides in from. */\r\nexport type DrawerSide = 'left' | 'right' | 'top' | 'bottom'\r\n\r\n/** Options accepted by the `Drawer` factory. */\r\nexport interface DrawerOptions {\r\n /** Which edge to slide in from. Defaults to `'right'`. */\r\n side?: DrawerSide\r\n /** Title shown in the header. */\r\n title?: string\r\n /** Initial body content. */\r\n content?: HTMLElement | string\r\n /** Closes the drawer when the backdrop is clicked. Defaults to `true`. */\r\n closeOnBackdrop?: boolean\r\n /** Closes the drawer on Escape. Defaults to `true`. */\r\n closeOnEscape?: boolean\r\n /** Called whenever the open state changes. */\r\n onOpenChange?: (open: boolean) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Drawer` element. */\r\nexport interface DrawerApi {\r\n /** The scrollable body container. */\r\n body: HTMLElement\r\n /** Opens the drawer. */\r\n open: () => void\r\n /** Closes the drawer. */\r\n close: () => void\r\n /** Returns whether the drawer is currently open. */\r\n isOpen: () => boolean\r\n /** Updates the header title text. */\r\n setTitle: (title: string) => void\r\n /** Replaces the body content. */\r\n setContent: (content: HTMLElement | string) => void\r\n /** Removes all listeners/subscriptions and detaches the drawer from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Drawer` is a real `HTMLDivElement` (the overlay) extended with `DrawerApi`. */\r\nexport type DrawerElement = HTMLDivElement & DrawerApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const drawerCss = `\r\n.linteau-drawer-overlay { position: fixed; inset: 0; background: color-mix(in oklch, black 55%, transparent); z-index: 1000 }\r\n.linteau-drawer-panel { position: fixed; background: var(--linteau-card); border: 1px solid var(--linteau-border); display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); transition: transform 200ms ease }\r\n.linteau-drawer-right { top: 0; right: 0; bottom: 0; width: min(360px, 90vw); transform: translateX(0) }\r\n.linteau-drawer-left { top: 0; left: 0; bottom: 0; width: min(360px, 90vw); transform: translateX(0) }\r\n.linteau-drawer-top { top: 0; left: 0; right: 0; height: min(320px, 80vh); transform: translateY(0) }\r\n.linteau-drawer-bottom { bottom: 0; left: 0; right: 0; height: min(320px, 80vh); transform: translateY(0) }\r\n.linteau-drawer-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid var(--linteau-border) }\r\n.linteau-drawer-title { font-size: 14px; font-weight: 600 }\r\n.linteau-drawer-close { background: transparent; border: none; color: var(--linteau-muted-foreground); cursor: pointer; display: flex; padding: 4px; border-radius: var(--linteau-radius-sm) }\r\n.linteau-drawer-body { padding: 16px; overflow-y: auto; flex: 1 }\r\n`\r\n\r\n/** Creates a slide-in panel anchored to a screen edge, ideal for side navigation or contextual forms. */\r\nexport function Drawer(options: DrawerOptions = {}): DrawerElement {\r\n assertDom('Drawer')\r\n ensureComponentStyles('drawer', drawerCss)\r\n const side = options.side ?? 'right'\r\n const closeOnBackdrop = options.closeOnBackdrop ?? true\r\n const closeOnEscape = options.closeOnEscape ?? true\r\n let isOpen = false\r\n let unlockScroll: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const overlay = el('div', cx(px('drawer-overlay'), px('hidden')))\r\n const panel = el('div', cx(px('drawer-panel'), px(`drawer-${side}`)))\r\n panel.setAttribute('role', 'dialog')\r\n panel.setAttribute('aria-modal', 'true')\r\n const header = el('div', px('drawer-header'))\r\n const titleEl = el('div', px('drawer-title'))\r\n titleEl.textContent = options.title ?? ''\r\n const closeButton = el('button', px('drawer-close'))\r\n closeButton.type = 'button'\r\n const closeIcon = Icon(icons.x, 16)\r\n if (closeIcon) closeButton.appendChild(closeIcon)\r\n header.append(titleEl, closeButton)\r\n const body = el('div', px('drawer-body'))\r\n if (options.content) fillContent(body, options.content)\r\n panel.append(header, body)\r\n overlay.appendChild(panel)\r\n function setOpen(value: boolean): void {\r\n isOpen = value\r\n overlay.classList.toggle(px('hidden'), !value)\r\n if (value) {\r\n unlockScroll = lockBodyScroll()\r\n if (closeOnEscape) unbindEscape = onEscapeKey(close)\r\n } else {\r\n unlockScroll?.()\r\n unlockScroll = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n options.onOpenChange?.(value)\r\n }\r\n function close(): void {\r\n if (isOpen) setOpen(false)\r\n }\r\n const backdropListener = (event: MouseEvent): void => {\r\n if (closeOnBackdrop && event.target === overlay) close()\r\n }\r\n overlay.addEventListener('mousedown', backdropListener)\r\n closeButton.addEventListener('click', close)\r\n const api: DrawerApi = {\r\n body,\r\n open() {\r\n setOpen(true)\r\n },\r\n close,\r\n isOpen() {\r\n return isOpen\r\n },\r\n setTitle(title) {\r\n titleEl.textContent = title\r\n },\r\n setContent(content) {\r\n fillContent(body, content)\r\n },\r\n destroy() {\r\n overlay.removeEventListener('mousedown', backdropListener)\r\n closeButton.removeEventListener('click', close)\r\n unlockScroll?.()\r\n unbindEscape?.()\r\n overlay.remove()\r\n }\r\n }\r\n return attachController(overlay, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { onClickOutside, onEscapeKey, positionFloating } from '../../core/overlay'\r\nimport type { FloatingPlacement } from '../../core/overlay'\r\nimport { fillContent } from '../../core/content'\r\n\r\n/** Options accepted by the `Popover` factory. */\r\nexport interface PopoverOptions {\r\n /** The element the popover is anchored to and toggled by. */\r\n anchor: HTMLElement\r\n /** Initial panel content. */\r\n content: HTMLElement | string\r\n /** Side of the anchor the panel appears on. Defaults to `'bottom'`. */\r\n placement?: FloatingPlacement\r\n /** Closes the popover when clicking outside it. Defaults to `true`. */\r\n closeOnClickOutside?: boolean\r\n}\r\n\r\n/** The runtime control surface attached to every `Popover` element. */\r\nexport interface PopoverApi {\r\n /** Opens the popover and positions it against its anchor. */\r\n open: () => void\r\n /** Closes the popover. */\r\n close: () => void\r\n /** Toggles between open and closed. */\r\n toggle: () => void\r\n /** Returns whether the popover is currently open. */\r\n isOpen: () => boolean\r\n /** Replaces the panel content. */\r\n setContent: (content: HTMLElement | string) => void\r\n /** Removes all listeners and detaches the popover from the DOM. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Popover` is a real `HTMLDivElement` (the floating panel) extended with `PopoverApi`. */\r\nexport type PopoverElement = HTMLDivElement & PopoverApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const popoverCss = `\r\n.linteau-popover { position: fixed; z-index: 1200; background: var(--linteau-card); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-md); padding: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4) }\r\n`\r\n\r\n/** Creates a floating panel anchored to another element, toggled by clicking that anchor. */\r\nexport function Popover(options: PopoverOptions): PopoverElement {\r\n assertDom('Popover')\r\n ensureComponentStyles('popover', popoverCss)\r\n const { anchor, placement = 'bottom', closeOnClickOutside = true } = options\r\n let isOpen = false\r\n let unbindOutside: (() => void) | null = null\r\n let unbindEscape: (() => void) | null = null\r\n const panel = el('div', cx(px('popover'), px('hidden')))\r\n fillContent(panel, options.content)\r\n function open(): void {\r\n if (isOpen) return\r\n isOpen = true\r\n document.body.appendChild(panel)\r\n panel.classList.remove(px('hidden'))\r\n positionFloating(anchor, panel, placement)\r\n if (closeOnClickOutside) unbindOutside = onClickOutside([anchor, panel], close)\r\n unbindEscape = onEscapeKey(close)\r\n }\r\n function close(): void {\r\n if (!isOpen) return\r\n isOpen = false\r\n panel.classList.add(px('hidden'))\r\n panel.remove()\r\n unbindOutside?.()\r\n unbindOutside = null\r\n unbindEscape?.()\r\n unbindEscape = null\r\n }\r\n function toggle(): void {\r\n if (isOpen) close()\r\n else open()\r\n }\r\n const anchorListener = (): void => toggle()\r\n anchor.addEventListener('click', anchorListener)\r\n const api: PopoverApi = {\r\n open,\r\n close,\r\n toggle,\r\n isOpen() {\r\n return isOpen\r\n },\r\n setContent(content) {\r\n fillContent(panel, content)\r\n },\r\n destroy() {\r\n anchor.removeEventListener('click', anchorListener)\r\n unbindOutside?.()\r\n unbindEscape?.()\r\n panel.remove()\r\n }\r\n }\r\n return attachController(panel, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\n\r\n/** A single selectable option within a `RadioGroup`. */\r\nexport interface RadioOptionItem {\r\n /** Visible label. */\r\n label: string\r\n /** Unique value identifying this option. */\r\n value: string\r\n /** Disables just this option. Defaults to `false`. */\r\n disabled?: boolean\r\n}\r\n\r\n/** Options accepted by the `RadioGroup` factory. */\r\nexport interface RadioGroupOptions {\r\n /** The list of selectable options. */\r\n items: RadioOptionItem[]\r\n /** Controlled value. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: string\r\n /** Disables every option. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user picks a new option. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `RadioGroup` element. */\r\nexport interface RadioGroupApi {\r\n /** Returns the currently selected value, if any. */\r\n getValue: () => string | undefined\r\n /** Programmatically selects a value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Detaches the group from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `RadioGroup` is a real `HTMLDivElement` extended with `RadioGroupApi`. */\r\nexport type RadioGroupElement = HTMLDivElement & RadioGroupApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const radioCss = `\r\n.linteau-radio-group { display: flex; flex-direction: column; gap: 8px }\r\n.linteau-radio-row { display: flex; align-items: center; gap: 8px; cursor: pointer }\r\n.linteau-radio-row.linteau-disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-radio { width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--linteau-border); background: var(--linteau-secondary); display: flex; align-items: center; justify-content: center; flex-shrink: 0 }\r\n.linteau-radio.linteau-checked { border-color: var(--linteau-primary) }\r\n.linteau-radio-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--linteau-primary); opacity: 0; transition: opacity 100ms ease }\r\n.linteau-radio.linteau-checked .linteau-radio-dot { opacity: 1 }\r\n`\r\n\r\n/** Creates a single-select group of radio rows. */\r\nexport function RadioGroup(options: RadioGroupOptions): RadioGroupElement {\r\n assertDom('RadioGroup')\r\n ensureComponentStyles('radio', radioCss)\r\n let value = options.value ?? options.defaultValue\r\n const groupDisabled = options.disabled ?? false\r\n const onChange = options.onChange\r\n const cleanupListeners: Array<() => void> = []\r\n const root = el('div', px('radio-group'))\r\n root.setAttribute('role', 'radiogroup')\r\n function render(): void {\r\n root.replaceChildren()\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n for (const item of options.items) {\r\n const itemDisabled = groupDisabled || (item.disabled ?? false)\r\n const row = el('div', cx(px('radio-row'), itemDisabled && px('disabled')))\r\n const dot = el('div', cx(px('radio'), item.value === value && px('checked')))\r\n dot.appendChild(el('div', px('radio-dot')))\r\n const label = document.createElement('span')\r\n label.textContent = item.label\r\n row.append(dot, label)\r\n const listener = (): void => {\r\n if (itemDisabled) return\r\n value = item.value\r\n render()\r\n onChange?.(item.value)\r\n }\r\n row.addEventListener('click', listener)\r\n cleanupListeners.push(() => row.removeEventListener('click', listener))\r\n root.appendChild(row)\r\n }\r\n }\r\n render()\r\n const api: RadioGroupApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n render()\r\n },\r\n destroy() {\r\n cleanupListeners.splice(0).forEach((fn) => fn())\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport { icons } from '../../svg/icons/index'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\n\r\n/** A single option rendered inside a `Select`. */\r\nexport interface SelectOptionItem {\r\n /** Visible label. */\r\n label: string\r\n /** Underlying value. */\r\n value: string\r\n /** Disables just this option. Defaults to `false`. */\r\n disabled?: boolean\r\n}\r\n\r\n/** Options accepted by the `Select` factory. */\r\nexport interface SelectOptions {\r\n /** Label rendered before the dropdown. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** The list of selectable options. */\r\n options: SelectOptionItem[]\r\n /** Controlled value. When provided together with `onChange`, you own the state. */\r\n value?: string\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: string\r\n /** Placeholder shown when no value is selected (renders as a disabled first option). */\r\n placeholder?: string\r\n /** Disables the whole control. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user picks a new option. */\r\n onChange?: (value: string) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Select` element. */\r\nexport interface SelectApi {\r\n /** Returns the currently selected value. */\r\n getValue: () => string\r\n /** Programmatically selects a value (does not trigger `onChange`). */\r\n setValue: (value: string) => void\r\n /** Replaces the full list of options, preserving selection where possible. */\r\n setOptions: (options: SelectOptionItem[]) => void\r\n /** Enables/disables the control. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the select from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Select` is a real `HTMLDivElement` (the field row) extended with `SelectApi`. */\r\nexport type SelectElement = HTMLDivElement & SelectApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const selectCss = `\r\n.linteau-select-wrap { position: relative }\r\n.linteau-select { appearance: none; background: var(--linteau-secondary); color: var(--linteau-foreground); border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-sm); padding: 6px 28px 6px 10px; font-size: 12px; font-family: inherit; cursor: pointer; transition: border-color 120ms ease }\r\n.linteau-select:disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-select:focus { outline: none; border-color: var(--linteau-ring); box-shadow: 0 0 0 2px color-mix(in oklch, var(--linteau-ring) 20%, transparent) }\r\n.linteau-select-chevron { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); pointer-events: none }\r\n`\r\n\r\n/** Creates a labeled native select dropdown, restyled to match the design system. */\r\nexport function Select(options: SelectOptions): SelectElement {\r\n assertDom('Select')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('select', selectCss)\r\n let items = options.options\r\n let value = options.value ?? options.defaultValue ?? items[0]?.value ?? ''\r\n const onChange = options.onChange\r\n const root = el('div', px('field-row'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n const selectWrap = el('div', px('select-wrap'))\r\n const select = el('select', px('select'))\r\n select.disabled = options.disabled ?? false\r\n function renderOptions(): void {\r\n select.replaceChildren()\r\n if (options.placeholder) {\r\n const placeholderOption = document.createElement('option')\r\n placeholderOption.value = ''\r\n placeholderOption.textContent = options.placeholder\r\n placeholderOption.disabled = true\r\n placeholderOption.selected = !value\r\n select.appendChild(placeholderOption)\r\n }\r\n for (const item of items) {\r\n const optionEl = document.createElement('option')\r\n optionEl.value = item.value\r\n optionEl.textContent = item.label\r\n optionEl.disabled = item.disabled ?? false\r\n optionEl.selected = item.value === value\r\n select.appendChild(optionEl)\r\n }\r\n }\r\n renderOptions()\r\n const chevron = Icon(icons.chevronDown, 12, { className: px('select-chevron') })!\r\n selectWrap.append(select, chevron)\r\n const listener = (): void => {\r\n value = select.value\r\n onChange?.(value)\r\n }\r\n select.addEventListener('change', listener)\r\n root.append(labelWrap, selectWrap)\r\n const api: SelectApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = newValue\r\n select.value = newValue\r\n },\r\n setOptions(newOptions) {\r\n items = newOptions\r\n renderOptions()\r\n },\r\n setDisabled(disabled) {\r\n select.disabled = disabled\r\n },\r\n destroy() {\r\n select.removeEventListener('change', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\n\r\n/** Options accepted by the `Slider` factory. */\r\nexport interface SliderOptions {\r\n /** Label rendered above the track. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Minimum value. */\r\n min: number\r\n /** Maximum value. */\r\n max: number\r\n /** Step increment. */\r\n step: number\r\n /** Controlled value. When provided together with `onChange`, you own the state. */\r\n value?: number\r\n /** Uncontrolled initial value, used only if `value` is omitted. */\r\n defaultValue?: number\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Formats the displayed value string. Defaults to `String(value)`. */\r\n format?: (value: number) => string\r\n /** Called on every input event with the new numeric value. */\r\n onChange?: (value: number) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Slider` element. */\r\nexport interface SliderApi {\r\n /** Returns the current numeric value. */\r\n getValue: () => number\r\n /** Programmatically sets the value (does not trigger `onChange`, clamped to `[min, max]`). */\r\n setValue: (value: number) => void\r\n /** Enables/disables the slider. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the slider from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Slider` is a real `HTMLDivElement` (the field wrapper) extended with `SliderApi`. */\r\nexport type SliderElement = HTMLDivElement & SliderApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const sliderCss = `\r\n.linteau-slider { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 999px; background: linear-gradient(to right, var(--linteau-primary) 0%, var(--linteau-primary) var(--linteau-fill, 0%), var(--linteau-secondary) var(--linteau-fill, 0%), var(--linteau-secondary) 100%); outline: none; transition: background 120ms ease }\r\n.linteau-slider:disabled { opacity: 0.5 }\r\n.linteau-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--linteau-primary); border: 2px solid var(--linteau-card); box-shadow: 0 0 0 1px var(--linteau-border); cursor: pointer; transition: transform 120ms ease }\r\n.linteau-slider::-webkit-slider-thumb:hover { transform: scale(1.15) }\r\n.linteau-slider::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--linteau-primary); border: 2px solid var(--linteau-card); cursor: pointer }\r\n`\r\n\r\n/** Creates a labeled range slider with a live value readout, supporting controlled and uncontrolled usage. */\r\nexport function Slider(options: SliderOptions): SliderElement {\r\n assertDom('Slider')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('slider', sliderCss)\r\n const { min, max, step } = options\r\n let value = options.value ?? options.defaultValue ?? min\r\n const format = options.format ?? ((v: number) => v.toString())\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n const valueEl = el('span', px('field-value'))\r\n valueEl.textContent = format(value)\r\n header.append(labelWrap, valueEl)\r\n const input = el('input', px('slider'))\r\n input.type = 'range'\r\n input.min = String(min)\r\n input.max = String(max)\r\n input.step = String(step)\r\n input.value = String(value)\r\n input.disabled = options.disabled ?? false\r\n function updateFill(v: number): void {\r\n const percent = ((v - min) / (max - min)) * 100\r\n input.style.setProperty('--linteau-fill', `${percent}%`)\r\n }\r\n updateFill(value)\r\n const listener = (): void => {\r\n value = Number(input.value)\r\n valueEl.textContent = format(value)\r\n updateFill(value)\r\n onChange?.(value)\r\n }\r\n input.addEventListener('input', listener)\r\n root.append(header, input)\r\n const api: SliderApi = {\r\n getValue() {\r\n return value\r\n },\r\n setValue(newValue) {\r\n value = Math.max(min, Math.min(max, newValue))\r\n input.value = String(value)\r\n valueEl.textContent = format(value)\r\n updateFill(value)\r\n },\r\n setDisabled(disabled) {\r\n input.disabled = disabled\r\n },\r\n destroy() {\r\n input.removeEventListener('input', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\nimport { sliderCss } from './Slider'\r\n\r\n/** A `[low, high]` numeric pair. */\r\nexport type RangeValue = [number, number]\r\n\r\n/** Options accepted by the `RangeSlider` factory. */\r\nexport interface RangeSliderOptions {\r\n /** Label rendered above the track. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Minimum value. */\r\n min: number\r\n /** Maximum value. */\r\n max: number\r\n /** Step increment. */\r\n step: number\r\n /** Controlled `[low, high]` value. */\r\n value?: RangeValue\r\n /** Uncontrolled initial `[low, high]` value, used only if `value` is omitted. */\r\n defaultValue?: RangeValue\r\n /** Disables both thumbs. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Formats each displayed bound. Defaults to `String(value)`. */\r\n format?: (value: number) => string\r\n /** Called on every change with the new `[low, high]` pair. */\r\n onChange?: (value: RangeValue) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `RangeSlider` element. */\r\nexport interface RangeSliderApi {\r\n /** Returns the current `[low, high]` value. */\r\n getValue: () => RangeValue\r\n /** Programmatically sets the value (does not trigger `onChange`). */\r\n setValue: (value: RangeValue) => void\r\n /** Enables/disables both thumbs. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the slider from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `RangeSlider` is a real `HTMLDivElement` (the field wrapper) extended with `RangeSliderApi`. */\r\nexport type RangeSliderElement = HTMLDivElement & RangeSliderApi\r\n\r\n/** This component's own CSS. Depends on `.linteau-slider` (registered via the imported `sliderCss`) for its thumbs. */\r\nexport const rangeSliderCss = `\r\n.linteau-range-track { position: relative; height: 20px; display: flex; align-items: center }\r\n.linteau-range-track::before { content: ''; position: absolute; left: 0; right: 0; height: 6px; border-radius: 999px; background: var(--linteau-secondary) }\r\n.linteau-range-track::after { content: ''; position: absolute; height: 6px; border-radius: 999px; background: var(--linteau-primary); left: var(--linteau-range-low, 0%); right: calc(100% - var(--linteau-range-high, 100%)) }\r\n.linteau-range-input { position: absolute; left: 0; right: 0; width: 100%; height: 20px; background: transparent; pointer-events: none; margin: 0 }\r\n.linteau-range-input::-webkit-slider-thumb { pointer-events: auto }\r\n.linteau-range-input::-moz-range-thumb { pointer-events: auto }\r\n`\r\n\r\n/** Creates a labeled dual-thumb range slider, supporting controlled and uncontrolled usage. */\r\nexport function RangeSlider(options: RangeSliderOptions): RangeSliderElement {\r\n assertDom('RangeSlider')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('slider', sliderCss)\r\n ensureComponentStyles('range-slider', rangeSliderCss)\r\n const { min, max, step } = options\r\n let [low, high] = options.value ?? options.defaultValue ?? [min, max]\r\n const format = options.format ?? ((v: number) => v.toString())\r\n const onChange = options.onChange\r\n const root = el('div', px('field'))\r\n const header = el('div', px('field-header'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n const valueEl = el('span', px('field-value'))\r\n header.append(labelWrap, valueEl)\r\n const track = el('div', px('range-track'))\r\n const inputLow = el('input', cx(px('slider'), px('range-input')))\r\n const inputHigh = el('input', cx(px('slider'), px('range-input')))\r\n for (const input of [inputLow, inputHigh]) {\r\n input.type = 'range'\r\n input.min = String(min)\r\n input.max = String(max)\r\n input.step = String(step)\r\n input.disabled = options.disabled ?? false\r\n }\r\n function syncDisplay(): void {\r\n valueEl.textContent = `${format(low)} - ${format(high)}`\r\n inputLow.value = String(low)\r\n inputHigh.value = String(high)\r\n track.style.setProperty('--linteau-range-low', `${((low - min) / (max - min)) * 100}%`)\r\n track.style.setProperty('--linteau-range-high', `${((high - min) / (max - min)) * 100}%`)\r\n }\r\n syncDisplay()\r\n const lowListener = (): void => {\r\n low = Math.min(Number(inputLow.value), high)\r\n syncDisplay()\r\n onChange?.([low, high])\r\n }\r\n const highListener = (): void => {\r\n high = Math.max(Number(inputHigh.value), low)\r\n syncDisplay()\r\n onChange?.([low, high])\r\n }\r\n inputLow.addEventListener('input', lowListener)\r\n inputHigh.addEventListener('input', highListener)\r\n track.append(inputLow, inputHigh)\r\n root.append(header, track)\r\n const api: RangeSliderApi = {\r\n getValue() {\r\n return [low, high]\r\n },\r\n setValue(value) {\r\n ;[low, high] = value\r\n syncDisplay()\r\n },\r\n setDisabled(disabled) {\r\n inputLow.disabled = disabled\r\n inputHigh.disabled = disabled\r\n },\r\n destroy() {\r\n inputLow.removeEventListener('input', lowListener)\r\n inputHigh.removeEventListener('input', highListener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\nimport { fieldBaseCss } from '../field/shared'\r\n\r\n/** Options accepted by the `Switch` factory. */\r\nexport interface SwitchOptions {\r\n /** Label rendered next to the toggle. */\r\n label: string\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Controlled checked state. When provided together with `onChange`, you own the state. */\r\n checked?: boolean\r\n /** Uncontrolled initial state, used only if `checked` is omitted. Defaults to `false`. */\r\n defaultChecked?: boolean\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user toggles the switch. */\r\n onChange?: (checked: boolean) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Switch` element. */\r\nexport interface SwitchApi {\r\n /** Returns the current checked state. */\r\n getValue: () => boolean\r\n /** Programmatically sets the checked state (does not trigger `onChange`). */\r\n setValue: (checked: boolean) => void\r\n /** Updates the label text. */\r\n setLabel: (label: string) => void\r\n /** Enables/disables the switch. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the switch from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Switch` is a real `HTMLDivElement` (the row) extended with `SwitchApi`. */\r\nexport type SwitchElement = HTMLDivElement & SwitchApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const switchCss = `\r\n.linteau-switch-row { display: flex; align-items: center; justify-content: space-between }\r\n.linteau-switch { width: 38px; height: 22px; border-radius: 999px; background: var(--linteau-secondary); border: 1px solid var(--linteau-border); padding: 2px; cursor: pointer; display: flex; align-items: center; transition: background 150ms ease }\r\n.linteau-switch:disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-switch.linteau-checked { background: var(--linteau-primary) }\r\n.linteau-switch-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--linteau-card); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1); transform: translateX(0) }\r\n.linteau-switch.linteau-checked .linteau-switch-thumb { transform: translateX(16px); background: var(--linteau-primary-foreground) }\r\n`\r\n\r\n/** Creates a labeled on/off toggle, supporting both controlled and uncontrolled usage. */\r\nexport function Switch(options: SwitchOptions): SwitchElement {\r\n assertDom('Switch')\r\n ensureComponentStyles('field-base', fieldBaseCss)\r\n ensureComponentStyles('switch', switchCss)\r\n let checked = options.checked ?? options.defaultChecked ?? false\r\n let disabled = options.disabled ?? false\r\n const onChange = options.onChange\r\n const root = el('div', px('switch-row'))\r\n const labelWrap = el('div', px('field-label'))\r\n if (options.icon) labelWrap.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const labelText = document.createElement('span')\r\n labelText.textContent = options.label\r\n labelWrap.appendChild(labelText)\r\n const track = el('button', px('switch'))\r\n track.type = 'button'\r\n track.setAttribute('role', 'switch')\r\n track.disabled = disabled\r\n const thumb = el('span', px('switch-thumb'))\r\n track.appendChild(thumb)\r\n function applyState(): void {\r\n track.classList.toggle(px('checked'), checked)\r\n track.setAttribute('aria-checked', String(checked))\r\n }\r\n applyState()\r\n const listener = (): void => {\r\n if (disabled) return\r\n checked = !checked\r\n applyState()\r\n onChange?.(checked)\r\n }\r\n track.addEventListener('click', listener)\r\n root.append(labelWrap, track)\r\n const api: SwitchApi = {\r\n getValue() {\r\n return checked\r\n },\r\n setValue(value) {\r\n checked = value\r\n applyState()\r\n },\r\n setLabel(newLabel) {\r\n labelText.textContent = newLabel\r\n },\r\n setDisabled(value) {\r\n disabled = value\r\n track.disabled = value\r\n },\r\n destroy() {\r\n track.removeEventListener('click', listener)\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { cx, px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Icon } from '../../svg/Icon'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** Visual style of a `Toggle`. */\r\nexport type ToggleVariant = 'default' | 'outline'\r\n/** Sizing preset of a `Toggle`. */\r\nexport type ToggleSize = 'sm' | 'default'\r\n\r\n/** Options accepted by the `Toggle` factory. */\r\nexport interface ToggleOptions {\r\n /** Visual style. Defaults to `'default'`. */\r\n variant?: ToggleVariant\r\n /** Sizing preset. Defaults to `'default'`. */\r\n size?: ToggleSize\r\n /** Optional icon rendered before the label. */\r\n icon?: IconInput\r\n /** Controlled pressed state. When provided together with `onPressedChange`, you own the state. */\r\n pressed?: boolean\r\n /** Uncontrolled initial pressed state, used only if `pressed` is omitted. Defaults to `false`. */\r\n defaultPressed?: boolean\r\n /** Disables interaction. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the user toggles the button. */\r\n onPressedChange?: (pressed: boolean) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `Toggle` element. */\r\nexport interface ToggleApi {\r\n /** Returns the current pressed state. */\r\n getPressed: () => boolean\r\n /** Programmatically sets the pressed state (does not trigger `onPressedChange`). */\r\n setPressed: (pressed: boolean) => void\r\n /** Enables/disables the toggle. */\r\n setDisabled: (disabled: boolean) => void\r\n /** Detaches the toggle from the DOM and its internal listener. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `Toggle` is a real `HTMLButtonElement` extended with `ToggleApi`. */\r\nexport type ToggleElement = HTMLButtonElement & ToggleApi\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const toggleCss = `\r\n.linteau-toggle {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n border-radius: var(--linteau-radius-sm);\r\n border: 1px solid transparent;\r\n background: transparent;\r\n color: var(--linteau-muted-foreground);\r\n font-size: 13px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: background 120ms ease, color 120ms ease, border-color 120ms ease;\r\n}\r\n.linteau-toggle-default { padding: 8px 12px }\r\n.linteau-toggle-sm { padding: 5px 8px; font-size: 12px }\r\n.linteau-toggle:hover:not(:disabled) { background: var(--linteau-accent); color: var(--linteau-foreground) }\r\n.linteau-toggle:disabled { opacity: 0.5; cursor: not-allowed }\r\n.linteau-toggle-outline { border-color: var(--linteau-border) }\r\n.linteau-toggle.linteau-pressed { background: var(--linteau-accent); color: var(--linteau-foreground) }\r\n`\r\n\r\n/** Creates a single pressable toggle button -- a two-state control (like a checkbox rendered as a button), useful for toolbar options (bold, italic, view modes). */\r\nexport function Toggle(text: string, options: ToggleOptions = {}): ToggleElement {\r\n assertDom('Toggle')\r\n ensureComponentStyles('toggle', toggleCss)\r\n const variant = options.variant ?? 'default'\r\n const size = options.size ?? 'default'\r\n let pressed = options.pressed ?? options.defaultPressed ?? false\r\n let disabled = options.disabled ?? false\r\n const onPressedChange = options.onPressedChange\r\n const button = el('button', cx(px('toggle'), px(`toggle-${size}`), variant === 'outline' && px('toggle-outline')))\r\n button.type = 'button'\r\n button.setAttribute('aria-pressed', String(pressed))\r\n button.disabled = disabled\r\n if (options.icon) button.appendChild(Icon(options.icon, 14, { className: px('icon') })!)\r\n const label = document.createElement('span')\r\n label.textContent = text\r\n button.appendChild(label)\r\n function applyState(): void {\r\n button.classList.toggle(px('pressed'), pressed)\r\n button.setAttribute('aria-pressed', String(pressed))\r\n }\r\n applyState()\r\n const listener = (): void => {\r\n if (disabled) return\r\n pressed = !pressed\r\n applyState()\r\n onPressedChange?.(pressed)\r\n }\r\n button.addEventListener('click', listener)\r\n const api: ToggleApi = {\r\n getPressed() {\r\n return pressed\r\n },\r\n setPressed(value) {\r\n pressed = value\r\n applyState()\r\n },\r\n setDisabled(value) {\r\n disabled = value\r\n button.disabled = value\r\n },\r\n destroy() {\r\n button.removeEventListener('click', listener)\r\n button.remove()\r\n }\r\n }\r\n return attachController(button, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { attachController } from '../../core/controller'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { Toggle } from './Toggle'\r\nimport type { ToggleSize, ToggleVariant } from './Toggle'\r\nimport type { IconInput } from '../../svg/types'\r\n\r\n/** A single item within a `ToggleGroup`. */\r\nexport interface ToggleGroupItem {\r\n /** Visible label. */\r\n label: string\r\n /** Unique value identifying this item. */\r\n value: string\r\n /** Optional icon shown before the label. */\r\n icon?: IconInput\r\n /** Disables just this item. Defaults to `false`. */\r\n disabled?: boolean\r\n}\r\n\r\n/** Options accepted by the `ToggleGroup` factory. */\r\nexport interface ToggleGroupOptions {\r\n /** The items rendered as toggles. */\r\n items: ToggleGroupItem[]\r\n /** `'single'` allows one selected item at a time; `'multiple'` allows several. Defaults to `'single'`. */\r\n type?: 'single' | 'multiple'\r\n /** Controlled selected value(s) -- a `string` in `'single'` mode, a `string[]` in `'multiple'` mode. */\r\n value?: string | string[]\r\n /** Uncontrolled initial value(s), used only if `value` is omitted. */\r\n defaultValue?: string | string[]\r\n /** Visual style applied to every item. Defaults to `'outline'`. */\r\n variant?: ToggleVariant\r\n /** Sizing preset applied to every item. Defaults to `'default'`. */\r\n size?: ToggleSize\r\n /** Disables every item. Defaults to `false`. */\r\n disabled?: boolean\r\n /** Called whenever the selection changes via user interaction. */\r\n onChange?: (value: string | string[]) => void\r\n}\r\n\r\n/** The runtime control surface attached to every `ToggleGroup` element. */\r\nexport interface ToggleGroupApi {\r\n /** Returns the current selected value(s). */\r\n getValue: () => string | string[]\r\n /** Programmatically sets the selected value(s) (does not trigger `onChange`). */\r\n setValue: (value: string | string[]) => void\r\n /** Detaches the group from the DOM and its internal listeners. */\r\n destroy: () => void\r\n}\r\n\r\n/** A `ToggleGroup` is a real `HTMLDivElement` extended with `ToggleGroupApi`. */\r\nexport type ToggleGroupElement = HTMLDivElement & ToggleGroupApi\r\n\r\n/** This component's own CSS. Depends on `.linteau-toggle`, which `Toggle()` registers itself the moment `ToggleGroup` renders its first item. */\r\nexport const toggleGroupCss = `\r\n.linteau-toggle-group { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--linteau-border); border-radius: var(--linteau-radius-sm) }\r\n`\r\n\r\n/** Creates a group of toggle buttons supporting single- or multiple-selection, useful for view/alignment/format pickers. */\r\nexport function ToggleGroup(options: ToggleGroupOptions): ToggleGroupElement {\r\n assertDom('ToggleGroup')\r\n ensureComponentStyles('toggle-group', toggleGroupCss)\r\n const type = options.type ?? 'single'\r\n const variant = options.variant ?? 'outline'\r\n const size = options.size ?? 'default'\r\n const groupDisabled = options.disabled ?? false\r\n const onChange = options.onChange\r\n let selected = new Set<string>(\r\n Array.isArray(options.value ?? options.defaultValue)\r\n ? (options.value ?? options.defaultValue) as string[]\r\n : options.value !== undefined || options.defaultValue !== undefined\r\n ? [(options.value ?? options.defaultValue) as string]\r\n : []\r\n )\r\n const root = el('div', px('toggle-group'))\r\n root.setAttribute('role', 'group')\r\n const toggles = new Map<string, ReturnType<typeof Toggle>>()\r\n function currentValue(): string | string[] {\r\n if (type === 'single') return Array.from(selected)[0] ?? ''\r\n return Array.from(selected)\r\n }\r\n function toggleItem(value: string): void {\r\n if (type === 'single') {\r\n selected = selected.has(value) ? new Set() : new Set([value])\r\n } else {\r\n if (selected.has(value)) selected.delete(value)\r\n else selected.add(value)\r\n }\r\n for (const [itemValue, toggle] of toggles) toggle.setPressed(selected.has(itemValue))\r\n onChange?.(currentValue())\r\n }\r\n for (const item of options.items) {\r\n const toggle = Toggle(item.label, {\r\n variant,\r\n size,\r\n icon: item.icon,\r\n pressed: selected.has(item.value),\r\n disabled: groupDisabled || (item.disabled ?? false),\r\n onPressedChange: () => toggleItem(item.value)\r\n })\r\n toggles.set(item.value, toggle)\r\n root.appendChild(toggle)\r\n }\r\n const api: ToggleGroupApi = {\r\n getValue() {\r\n return currentValue()\r\n },\r\n setValue(value) {\r\n selected = new Set(Array.isArray(value) ? value : [value])\r\n for (const [itemValue, toggle] of toggles) toggle.setPressed(selected.has(itemValue))\r\n },\r\n destroy() {\r\n for (const toggle of toggles.values()) toggle.destroy()\r\n root.remove()\r\n }\r\n }\r\n return attachController(root, api)\r\n}","import { assertDom, el } from '../../core/dom'\r\nimport { px } from '../../core/classNames'\r\nimport { ensureComponentStyles } from '../../core/styleInjector'\r\nimport { positionFloating } from '../../core/overlay'\r\nimport type { FloatingPlacement } from '../../core/overlay'\r\nimport type { Destroyable } from '../../core/types'\r\n\r\n/** Options accepted by the `Tooltip` factory. */\r\nexport interface TooltipOptions {\r\n /** Side of the anchor the tooltip appears on. Defaults to `'top'`. */\r\n placement?: FloatingPlacement\r\n /** Milliseconds to wait before showing, after hover/focus starts. Defaults to `200`. */\r\n delay?: number\r\n}\r\n\r\n/**\r\n * The runtime control surface returned by `Tooltip`. Unlike most components, this is a\r\n * plain controller -- not an element -- because it attaches behavior to an existing anchor\r\n * rather than creating a new one to place in your layout.\r\n */\r\nexport interface TooltipApi extends Destroyable {\r\n /** Updates the tooltip's text content. */\r\n setContent: (content: string) => void\r\n}\r\n\r\n/** This component's own CSS, colocated and self-injected on first use. */\r\nexport const tooltipCss = `\r\n.linteau-tooltip { position: fixed; z-index: 1300; background: var(--linteau-foreground); color: var(--linteau-background); font-size: 11px; font-weight: 500; padding: 5px 8px; border-radius: var(--linteau-radius-sm); pointer-events: none; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3) }\r\n`\r\n\r\n/** Attaches a floating text tooltip to `anchor`, shown on hover/focus. */\r\nexport function Tooltip(anchor: HTMLElement, content: string, options: TooltipOptions = {}): TooltipApi {\r\n assertDom('Tooltip')\r\n ensureComponentStyles('tooltip', tooltipCss)\r\n const placement = options.placement ?? 'top'\r\n const delay = options.delay ?? 200\r\n let text = content\r\n let showTimer: ReturnType<typeof setTimeout> | null = null\r\n const tooltip = el('div', px('tooltip'))\r\n tooltip.textContent = text\r\n tooltip.style.display = 'none'\r\n function show(): void {\r\n showTimer = setTimeout(() => {\r\n document.body.appendChild(tooltip)\r\n tooltip.style.display = 'block'\r\n positionFloating(anchor, tooltip, placement)\r\n }, delay)\r\n }\r\n function hide(): void {\r\n if (showTimer) clearTimeout(showTimer)\r\n tooltip.style.display = 'none'\r\n tooltip.remove()\r\n }\r\n anchor.addEventListener('mouseenter', show)\r\n anchor.addEventListener('mouseleave', hide)\r\n anchor.addEventListener('focus', show)\r\n anchor.addEventListener('blur', hide)\r\n return {\r\n setContent(newContent) {\r\n text = newContent\r\n tooltip.textContent = text\r\n },\r\n destroy() {\r\n hide()\r\n anchor.removeEventListener('mouseenter', show)\r\n anchor.removeEventListener('mouseleave', hide)\r\n anchor.removeEventListener('focus', show)\r\n anchor.removeEventListener('blur', hide)\r\n }\r\n }\r\n}"],"mappings":"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","names":["description","value","calendar","menu","menu"]}