entasis 0.9.3 → 0.10.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 (82) hide show
  1. package/dist/components/ButtonGroup/ButtonGroup.svelte +10 -4
  2. package/dist/components/ButtonGroup/buttonGroup.mcp.d.ts +1 -1
  3. package/dist/components/ButtonGroup/buttonGroup.mcp.js +23 -3
  4. package/dist/components/ButtonGroup/buttonGroup.props.d.ts +19 -5
  5. package/dist/components/Chart/Chart.svelte +1 -1
  6. package/dist/components/Chart/chart.cartesian.js +3 -2
  7. package/dist/components/Chart/chart.fit.d.ts +53 -0
  8. package/dist/components/Chart/chart.fit.js +81 -0
  9. package/dist/components/Chart/chart.mcp.d.ts +1 -1
  10. package/dist/components/Chart/chart.mcp.js +2 -1
  11. package/dist/components/Chart/chart.polar.js +137 -18
  12. package/dist/components/Chart/chart.polar.props.d.ts +5 -0
  13. package/dist/components/Chart/chart.proportion.js +12 -6
  14. package/dist/components/Chart/chart.relation.network.js +32 -4
  15. package/dist/components/Chart/chart.relation.sankey.js +53 -6
  16. package/dist/components/Chart/chart.relation.tree.js +84 -24
  17. package/dist/components/Chart/chart.series.props.d.ts +6 -0
  18. package/dist/components/Chart/chart.state.svelte.d.ts +1 -0
  19. package/dist/components/Chart/chart.state.svelte.js +9 -6
  20. package/dist/components/Chart/chart.viewport.svelte.d.ts +1 -0
  21. package/dist/components/Chart/chart.viewport.svelte.js +25 -7
  22. package/dist/components/DataTable/DataTable.svelte +25 -8
  23. package/dist/components/DataTable/DataTableRow.svelte +33 -10
  24. package/dist/components/DataTable/dataTable.mcp.d.ts +1 -1
  25. package/dist/components/DataTable/dataTable.mcp.js +12 -1
  26. package/dist/components/DataTable/dataTable.model.svelte.js +4 -3
  27. package/dist/components/DataTable/dataTable.props.d.ts +17 -0
  28. package/dist/components/DataTable/dataTable.theme.d.ts +12 -0
  29. package/dist/components/DataTable/dataTable.theme.js +3 -2
  30. package/dist/components/DataTable/index.d.ts +1 -1
  31. package/dist/components/Dialog/Dialog.svelte +12 -7
  32. package/dist/components/Dialog/dialog.state.svelte.d.ts +2 -1
  33. package/dist/components/Dialog/dialog.state.svelte.js +7 -7
  34. package/dist/components/Dialog/dialog.theme.js +1 -1
  35. package/dist/components/FloatingWindow/floatingWindow.theme.js +1 -1
  36. package/dist/components/Form/Select/Select.svelte +3 -1
  37. package/dist/components/Form/Select/select.align.d.ts +3 -2
  38. package/dist/components/Form/Select/select.align.js +11 -4
  39. package/dist/components/PageShell/pageShell.state.svelte.d.ts +1 -1
  40. package/dist/components/PageShell/pageShell.state.svelte.js +6 -13
  41. package/dist/components/Popover/Popover.svelte +5 -5
  42. package/dist/components/Popover/index.d.ts +1 -1
  43. package/dist/components/Popover/popover.mcp.d.ts +1 -1
  44. package/dist/components/Popover/popover.mcp.js +33 -6
  45. package/dist/components/Popover/popover.state.svelte.d.ts +9 -1
  46. package/dist/components/Popover/popover.state.svelte.js +61 -8
  47. package/dist/components/Popover/popover.theme.js +1 -1
  48. package/dist/components/Sidebar/SidebarDesktopShell.svelte +26 -6
  49. package/dist/components/Sidebar/sidebar.theme.js +1 -1
  50. package/dist/components/Theme/index.d.ts +1 -1
  51. package/dist/components/Theme/index.js +1 -1
  52. package/dist/components/Theme/theme.mcp.d.ts +1 -1
  53. package/dist/components/Theme/theme.mcp.js +3 -0
  54. package/dist/components/Theme/theme.state.svelte.d.ts +4 -0
  55. package/dist/components/Theme/theme.state.svelte.js +4 -0
  56. package/dist/components/Tooltip/Tooltip.svelte +2 -4
  57. package/dist/components/Tooltip/tooltip.attachment.svelte.js +5 -0
  58. package/dist/components/Tooltip/tooltip.mcp.d.ts +1 -1
  59. package/dist/components/Tooltip/tooltip.mcp.js +4 -2
  60. package/dist/generated/componentAliases.d.ts +1 -0
  61. package/dist/generated/componentAliases.js +1 -0
  62. package/dist/generated/componentContract.d.ts +13 -3
  63. package/dist/generated/componentContract.js +15 -1
  64. package/dist/generated/componentMcpRegistry.d.ts +7 -6
  65. package/dist/generated/componentMcpRegistry.js +2 -0
  66. package/dist/i18n/ar.js +1 -1
  67. package/dist/i18n/de.js +1 -1
  68. package/dist/i18n/en.js +1 -1
  69. package/dist/i18n/es.js +1 -1
  70. package/dist/i18n/fr.js +1 -1
  71. package/dist/i18n/pt.js +1 -1
  72. package/dist/i18n/zh.js +1 -1
  73. package/dist/tailwind/colors.d.ts +10 -3
  74. package/dist/tailwind/colors.js +6 -0
  75. package/dist/tailwind/palette.d.ts +5 -0
  76. package/dist/tailwind/palette.js +4 -0
  77. package/dist/tailwind/palette.mcp.d.ts +1 -0
  78. package/dist/tailwind/palette.mcp.js +34 -0
  79. package/dist/utils/layers.svelte.js +9 -8
  80. package/dist/utils/registry.svelte.d.ts +21 -0
  81. package/dist/utils/registry.svelte.js +49 -0
  82. package/package.json +8 -1
@@ -1,4 +1,5 @@
1
1
  import { bind } from '../../utils/state.svelte.js';
2
+ import { Registry } from '../../utils/registry.svelte.js';
2
3
  import { getContext, hasContext, onMount, setContext, untrack } from 'svelte';
3
4
  import { useTheme } from '../Theme/theme.state.svelte.js';
4
5
  import { computePosition, autoUpdate, hide, offset, shift, flip } from '@floating-ui/dom';
@@ -14,6 +15,10 @@ const PopoverOptionsBase = class {
14
15
  };
15
16
  // The one place the trigger's semantic state becomes ARIA, for triggers the library cannot
16
17
  // pass props to (a snippet trigger carrying `{@attach popover.reference}`).
18
+ /** Elements that may carry popup ARIA state. */
19
+ const POPUP_CONTROL = 'button, a[href], input, select, textarea, summary, [role="button"], [role="link"], [role="combobox"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="option"], [role="treeitem"], [role="gridcell"], [role="switch"], [role="checkbox"]';
20
+ /** Elements the browser already focuses and activates from the keyboard. */
21
+ const NATIVE_CONTROL = 'button, a[href], input, select, textarea, summary';
17
22
  const TRIGGER_ARIA = {
18
23
  haspopup: 'aria-haspopup',
19
24
  expanded: 'aria-expanded',
@@ -29,7 +34,11 @@ export class PopoverState extends PopoverOptionsBase {
29
34
  // Trigger-matched width (fitTrigger), applied to the panel.
30
35
  triggerWidth = $state(null);
31
36
  parent = getContext('popover');
32
- children = $state([]);
37
+ // Nested popovers join while they mount and leave when torn down; see `Registry`.
38
+ #children = new Registry();
39
+ get children() {
40
+ return this.#children.items;
41
+ }
33
42
  hasChildOpen = $derived(this.children.some((d) => d.isOpen));
34
43
  hasTransitioned = $state(false);
35
44
  theme = useTheme();
@@ -84,12 +93,7 @@ export class PopoverState extends PopoverOptionsBase {
84
93
  },
85
94
  delay: this.delay
86
95
  });
87
- addChild = (child) => () => {
88
- this.children.push(child);
89
- return () => {
90
- this.children = this.children.filter((d) => d.id !== child.id);
91
- };
92
- };
96
+ addChild = (child) => () => this.#children.add(child);
93
97
  constructor(options) {
94
98
  super();
95
99
  bind(this, options);
@@ -109,7 +113,10 @@ export class PopoverState extends PopoverOptionsBase {
109
113
  close = () => {
110
114
  this.setOpen(false);
111
115
  };
116
+ /** Calls to `setOpen`, direct or through `open`, `close` and `toggle`, unchanged state included. */
117
+ #openRequests = 0;
112
118
  setOpen = (nextOpen) => {
119
+ this.#openRequests += 1;
113
120
  if (this.isOpen === nextOpen)
114
121
  return;
115
122
  this.isOpen = nextOpen;
@@ -236,7 +243,7 @@ export class PopoverState extends PopoverOptionsBase {
236
243
  // Keep the trigger's ARIA in sync whichever way it was rendered (snippet or Button).
237
244
  // Only real controls carry aria-haspopup/aria-expanded; a wrapper div or a
238
245
  // presentational span used as the anchor must not (axe: aria-allowed-attr).
239
- const canCarryPopupState = node.matches('button, a[href], input, select, textarea, summary, [role="button"], [role="link"], [role="combobox"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="option"], [role="treeitem"], [role="gridcell"], [role="switch"], [role="checkbox"]');
246
+ const canCarryPopupState = node.matches(POPUP_CONTROL);
240
247
  $effect(() => {
241
248
  if (!canCarryPopupState)
242
249
  return;
@@ -261,6 +268,52 @@ export class PopoverState extends PopoverOptionsBase {
261
268
  };
262
269
  });
263
270
  };
271
+ /**
272
+ * Makes any element a complete trigger: it anchors the panel (as \`reference\` does), toggles
273
+ * it on click when \`openOnClick\` allows, and keeps \`aria-expanded\` and friends in sync.
274
+ * An element that is not already a control also gets \`role="button"\`, \`tabindex="0"\` and
275
+ * Enter/Space activation, so a card or an avatar opens the panel from the keyboard too.
276
+ */
277
+ trigger = (node) => {
278
+ const nativeControl = node.matches(NATIVE_CONTROL);
279
+ if (!node.matches(POPUP_CONTROL) && !node.hasAttribute('role')) {
280
+ node.setAttribute('role', 'button');
281
+ }
282
+ if (!nativeControl && !node.hasAttribute('tabindex'))
283
+ node.tabIndex = 0;
284
+ // The element's own handler wins. One that still opens, closes or toggles the popover
285
+ // (`onclick={popover.toggle}` kept from before this attachment existed) has acted by the
286
+ // time the event finishes dispatching, so the default toggle waits until then and runs only
287
+ // if nothing asked for an open state meanwhile; toggling regardless would undo that call.
288
+ let pending;
289
+ const activate = () => {
290
+ if (!this.openOnClick)
291
+ return;
292
+ const requests = this.#openRequests;
293
+ clearTimeout(pending);
294
+ pending = setTimeout(() => {
295
+ if (this.#openRequests === requests)
296
+ this.toggle();
297
+ });
298
+ };
299
+ const onKeydown = (event) => {
300
+ if (nativeControl || event.target !== node)
301
+ return;
302
+ if (event.key !== 'Enter' && event.key !== ' ')
303
+ return;
304
+ event.preventDefault();
305
+ activate();
306
+ };
307
+ node.addEventListener('click', activate);
308
+ node.addEventListener('keydown', onKeydown);
309
+ const offReference = this.reference(node);
310
+ return () => {
311
+ clearTimeout(pending);
312
+ node.removeEventListener('click', activate);
313
+ node.removeEventListener('keydown', onKeydown);
314
+ offReference?.();
315
+ };
316
+ };
264
317
  }
265
318
  // Use interface merging to add the properties
266
319
  export const usePopoverContext = () => {
@@ -12,7 +12,7 @@ const defaultPopoverContainer = cva({
12
12
  // `inline` keeps the panel in normal flow where the component sits: no portal, no
13
13
  // fixed positioning, no floating-ui placement.
14
14
  inline: 'static h-fit w-fit',
15
- mobileSheet: 'inset-0 flex h-dvh w-dvw max-w-none items-end justify-center overflow-hidden bg-neutral/40 backdrop-blur-xs'
15
+ mobileSheet: 'inset-0 flex h-dvh w-dvw max-w-none items-end justify-center overflow-hidden bg-black/40 backdrop-blur-xs dark:bg-black/60'
16
16
  }
17
17
  },
18
18
  defaultVariants: {
@@ -101,6 +101,9 @@
101
101
  let edgeTriggerRef: HTMLButtonElement | null = $state(null);
102
102
  let activityBarRef: HTMLElement | null = $state(null);
103
103
 
104
+ const TEXT_ENTRY =
105
+ 'input:not([type="button"],[type="checkbox"],[type="radio"],[type="range"],[type="submit"],[type="reset"]), textarea, select, [contenteditable]:not([contenteditable="false"])';
106
+
104
107
  let focusInside = $state(false);
105
108
  let pointerInside = $state(false);
106
109
 
@@ -161,6 +164,22 @@
161
164
  focusInside = false;
162
165
  });
163
166
 
167
+ // Only the keyboard's focus pins a peek. A click focuses the button it lands on, and focus the
168
+ // page moves after a click (a navigation putting it back on the clicked link) belongs to that
169
+ // click too: either way the panel stayed open after the pointer left the rail. So the input
170
+ // used last decides, as `:focus-visible` does: Tab, or Escape handing focus back from a menu,
171
+ // pins; a press does not. A text field pins either way, so typing never loses the panel.
172
+ let lastInput: 'pointer' | 'keyboard' = 'keyboard';
173
+ $effect(() => {
174
+ const offs = [
175
+ on(window, 'pointerdown', () => (lastInput = 'pointer'), { capture: true }),
176
+ on(window, 'keydown', () => (lastInput = 'keyboard'), { capture: true })
177
+ ];
178
+ return () => offs.forEach((off) => off());
179
+ });
180
+ const pinsPeek = (target: EventTarget | null) =>
181
+ lastInput === 'keyboard' || (target instanceof Element && target.matches(TEXT_ENTRY));
182
+
164
183
  $effect(() => {
165
184
  const nodes = peekRegion;
166
185
  if (!nodes.length) return;
@@ -168,9 +187,9 @@
168
187
  const isInside = (target: EventTarget | null) =>
169
188
  target instanceof Node && nodes.some((node) => node.contains(target));
170
189
  const offs = nodes.flatMap((node) => [
171
- on(node, 'focusin', () => {
172
- focusInside = true;
173
- if (canHoverExpand) hoverExpanded = true;
190
+ on(node, 'focusin', (event) => {
191
+ focusInside = pinsPeek(event.target);
192
+ if (focusInside && canHoverExpand) hoverExpanded = true;
174
193
  }),
175
194
  on(node, 'focusout', (event) => {
176
195
  focusInside = isInside(event.relatedTarget);
@@ -189,7 +208,8 @@
189
208
  // The activity bar is part of the sidebar: hovering it opens the collapsed panel the way the
190
209
  // edge strip (or `expandOnHover`) does, and a peek stays open while the pointer or focus is on
191
210
  // the rail, so switching sections from it never closes the panel it is switching. Keyboard
192
- // focus only keeps a peek: tabbing through the rail does not pop the panel out.
211
+ // focus only keeps a peek: tabbing through the rail does not pop the panel out, and a click
212
+ // keeps it only until the pointer leaves.
193
213
  $effect(() => {
194
214
  const rail = activityBarRef;
195
215
  if (!rail) return;
@@ -204,8 +224,8 @@
204
224
  on(rail, 'pointerleave', (event) => {
205
225
  pointerInside = isInside(event.relatedTarget);
206
226
  }),
207
- on(rail, 'focusin', () => {
208
- if (isPeeking) focusInside = true;
227
+ on(rail, 'focusin', (event) => {
228
+ focusInside = isPeeking && pinsPeek(event.target);
209
229
  }),
210
230
  on(rail, 'focusout', (event) => {
211
231
  focusInside = isInside(event.relatedTarget);
@@ -719,7 +719,7 @@ const defaultEdgeTrigger = cva({
719
719
  base: 'absolute inset-y-0 z-50 hidden w-3 bg-transparent outline-none md:block after:absolute after:inset-y-0 after:w-px after:bg-transparent after:transition-[background-color] after:duration-normal after:ease-standard hover:after:bg-neutral/45 focus-visible:ring-2 focus-visible:ring-focus/50 data-[side=left]:left-0 data-[side=left]:cursor-e-resize data-[side=left]:after:left-0 data-[side=right]:right-0 data-[side=right]:cursor-w-resize data-[side=right]:after:right-0'
720
720
  });
721
721
  const defaultOverlay = cva({
722
- base: 'fixed inset-0 z-40 bg-neutral/35 md:hidden'
722
+ base: 'fixed inset-0 z-40 bg-black/40 md:hidden dark:bg-black/60'
723
723
  });
724
724
  const defaultMobilePanel = cva({
725
725
  base: 'flex h-full min-h-0 w-[var(--sidebar-width-mobile)] flex-col bg-surface-floating text-neutral md:hidden',
@@ -1,5 +1,5 @@
1
1
  export { default as Theme } from './Theme.svelte';
2
- export { ThemeState, useDefaultColor } from './theme.state.svelte.js';
2
+ export { ThemeState, useDefaultColor, useTheme } from './theme.state.svelte.js';
3
3
  export type { ThemeProps } from './theme.props.js';
4
4
  export { defaultThemeSpacingScale, typeScalePresets, type ThemeDesignTokenMap, type ThemeDesignTokens, type ThemeRadius, type ThemeSpacing, type ThemeSpacingScale, type ThemeSpacingStep, type TypeScaleOptions, type TypeScalePreset, type TypeScaleRatio } from './theme.designTokens.js';
5
5
  export { themeTransitions, type ThemeTransition } from './themeTransition.js';
@@ -1,5 +1,5 @@
1
1
  export { default as Theme } from './Theme.svelte';
2
- export { ThemeState, useDefaultColor } from './theme.state.svelte.js';
2
+ export { ThemeState, useDefaultColor, useTheme } from './theme.state.svelte.js';
3
3
  export { defaultThemeSpacingScale, typeScalePresets } from './theme.designTokens.js';
4
4
  export { themeTransitions } from './themeTransition.js';
5
5
  export { focusRing, selectedSoft, selectedSolid } from './theme.recipes.js';
@@ -1 +1 @@
1
- export declare const themeDescription = "\n# Theme\n\n`Theme` owns global theme selection, runtime design tokens, shared overlay state, and theme\ntransitions. Wrap the application once and use the `ThemeState` received by the children snippet.\n\n## Runtime design tokens\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme, type ThemeDesignTokenMap } from 'entasis/theme';\n\n\tlet spacing = $state<'small' | 'normal' | 'large'>('normal');\n\tconst designTokens = $derived({\n\t\tlight: {\n\t\t\tspacing,\n\t\t\tspacingScale: { xs: 1, sm: 1.5, md: 2, lg: 3, xl: 4 },\n\t\t\tradius: 'normal',\n\t\t\ttypeScale: 'default',\n\t\t\traisedWithBorder: true,\n\t\t\tdefaultColor: 'neutral'\n\t\t},\n\t\tdark: {\n\t\t\tspacing,\n\t\t\tspacingScale: { xs: 1, sm: 1.5, md: 2, lg: 3, xl: 4 },\n\t\t\tradius: 'small',\n\t\t\ttypeScale: 'compact',\n\t\t\traisedWithBorder: false,\n\t\t\tdefaultColor: 'neutral'\n\t\t}\n\t} satisfies ThemeDesignTokenMap<readonly ['light', 'dark']>);\n</script>\n\n<Theme {designTokens} transition=\"radial-top-right\">\n\t{#snippet children(theme)}\n\t\t<button onclick={() => (spacing = spacing === 'small' ? 'large' : 'small')}>\n\t\t\tChange density\n\t\t</button>\n\t\t<button onclick={() => (theme.theme = theme.resolvedTheme === 'dark' ? 'light' : 'dark')}>\n\t\t\tToggle color scheme\n\t\t</button>\n\t{/snippet}\n</Theme>\n```\n\n`designTokens` is keyed by logical theme name and respects the `attribute` and `value` props.\nEleven presets ship as `themePresets` (`dense`, `compact`, `balanced`, `comfortable`, `spacious`,\n`sharp`, `rounded`, `display`, `editorial`, `glass`, `terminal`): `designTokens={{ light: themePresets.glass.tokens, dark: themePresets.glass.tokens }}`.\nChanging the controlled object updates already-rendered Tailwind utilities without rebuilding CSS.\n\n### ThemeDesignTokens\n\n- `spacing`: `'small' | 'normal' | 'large' | number`. Globally scales density.\n- `spacingScale`: partial overrides for the strictly increasing `xs`, `sm`, `md`, `lg`,\n and `xl` spacing multipliers. Defaults to 1/1.5/2/3/4.\n- `radius`: `'none' | 'subtile' | 'small' | 'normal' | 'large' | 'round' | number`.\n Controls take the full multiplier; surface steps (`lg` and up) stop at `large` (1.5\u00D7).\n- `typeScale`: `'compact' | 'default' | 'comfortable' | 'large' | TypeScaleOptions`.\n- `raisedWithBorder`: toggles the border used by `raised-*` utilities.\n- `defaultColor`: `Colors` role kit chrome inherits when a control omits `color`.\n Defaults to `neutral`. Set `primary` to restore an accent-colored kit. Compiles the\n current-color family (`--color`, `--color-readable`, muted/contrast/light/dark variants)\n and `--default-color` onto the theme selector. Do not set `data-color` on `html`.\n- `focusColor`, `selectedColor`, `hoverColor`, `pressedColor`: the four `Colors` **state\n roles**. They pin, for the whole theme, what a focus ring, a persistent selection and the\n transient hover/pressed layer look like, independently of the role of the control the state\n lands on. They compile `--color-focus`, `--color-selected` (plus its `-contrast`,\n `-readable` and `-muted-readable` companions), `--color-hover` and\n `--color-pressed` onto the theme selector. There is no `--color-selected-muted`: the soft\n fill is a translucent tint of `--color-selected` at `--state-selected-opacity`, so it reads\n on any surface. None is declared at `:root`: every use site\n falls back to the matching current role (`ring-focus` is\n `var(--color-focus, var(--color))`, `bg-selected-muted` tints\n `var(--color-selected, var(--color))`, the state layer is\n `var(--color-hover, currentColor)` and on `:active`\n `var(--color-pressed, var(--color-hover, currentColor))`), so leaving them unset changes\n nothing and `data-color` keeps moving the states with `--color`. Theme-level only: there is\n no per-component override. An unknown role throws.\n\nComponent-level density remains a local variant. It selects utility classes whose values inherit\nthe active global spacing token.\n\nGenerated interfaces should use the public `xs | sm | md | lg | xl` vocabulary through component\nprops and named gap/padding utilities. `micro` and `layout-*` are internal recipe tokens. Prefer\nparent-owned gaps over child margins; do not emit arbitrary spacing or unsupported radius values.\n\n## Theme selection\n\nThe selection props wrap `svelte-themes`: `themes`, `defaultTheme`, `forcedTheme`,\n`systemTheme`, `syncColorScheme`, `transitionOnChange`, `storageKey`, `attribute`,\n`value`, and `colorScheme`. The default themes are light and dark, with system selection\nenabled. `systemTheme`, `syncColorScheme`, and `transitionOnChange` all default to\n`true`; they map onto the library's `enableSystem`, `enableColorScheme`, and\n`disableTransitionOnChange` options.\n\n`ThemeState` exposes `theme`, `resolvedTheme`, `themes`, and `systemTheme`. Assign\n`theme.theme` to switch themes. The optional `transition` prop applies a named view transition;\nunsupported browsers and reduced-motion users switch instantly.\n\n`spinnerVariant` sets the global default spinner animation. The children snippet is required.\n\n## Motion tokens\n\nMotion is a token scale like spacing and radius: five duration steps and four easing roles.\n`motion` retunes them app-wide; an omitted token keeps its default.\n\n| Duration | Default | | Easing role | Default |\n| ---------- | ------- | --- | ------------ | ------------- |\n| `instant` | 0ms | | `standard` | `cubicInOut` |\n| `fast` | 100ms | | `enter` | `cubicOut` |\n| `normal` | 200ms | | `exit` | `cubicIn` |\n| `slow` | 300ms | | `emphasized` | `backOut` |\n| `slower` | 500ms | | | |\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme motion={{ duration: { normal: 150, slow: 260 }, easing: { standard: 'quintOut' } }}>\n\t{@render children()}\n</Theme>\n```\n\nThe Tailwind plugin emits the same scale as CSS variables on `html` (`--duration-normal`,\n`--ease-standard`, ...) plus the matching `duration-*` / `ease-*` utilities, so CSS transitions\nand Svelte transitions read one set of numbers. The `motion` prop rewrites those variables on\n`html` at runtime and `designTokens.motion` rewrites them again per theme, layered over the prop;\n`ThemeState.motion` resolves through the same two rungs, so the utilities and the presets never\ndisagree. `ThemeState.transition` is a deprecated alias for its `normal` duration and `standard`\neasing. Reduced motion resolves every duration to 0 and collapses the `--duration-*` variables via\nthe `data-entasis-reduce-motion` attribute on `html`.\n\nComponents keep their own transition in a reserved `motion` slot on their theme, so the `theme`\nprop covers motion as well as classes:\n\n```svelte\n<script lang=\"ts\">\n\timport { Dialog } from 'entasis/dialog';\n</script>\n\n<Dialog theme={{ motion: { duration: 'fast', easing: 'emphasized' } }} title=\"Quick\">Body</Dialog>\n```\n\n## Component theme registry\n\n`components` sets app-wide component theme defaults without a wrapper component per component:\nit is keyed by theme name (`dialog`, `button`, ...) and each entry takes the same slots as that\ncomponent's `theme` prop, the `motion` slot included. A `set<Component>Theme` call in a subtree\nbeats the registry, and an instance `theme` prop beats both \u2014 per slot: each rung layers on the one\nbelow it, so a subtree that restyles one slot keeps the registry's others.\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme\n\tcomponents={{\n\t\tdialog: { motion: { duration: 'fast' }, content: { base: 'rounded-2xl' } },\n\t\tbutton: { root: { base: 'tracking-wide' } }\n\t}}\n>\n\t{@render children()}\n</Theme>\n```\n\n## Reduced motion\n\n`reduceMotion` forces reduced motion on (`true`) or off (`false`) for every entasis animation,\noverriding the OS `prefers-reduced-motion` setting; omit it to follow the OS. The live result is\nexposed as `ThemeState.preferReducesMotion` (reactive, so it updates when the OS setting changes)\nand mirrored as a `data-entasis-reduce-motion` attribute on `html` for CSS-only animations.\n\n```svelte\n<script>\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme reduceMotion>{@render children()}</Theme>\n```\n\n## Build-time boundary\n\nThe Tailwind plugin still generates color palettes and registers utility names, variants,\nkeyframes, and spinner CSS. Spacing, radius, typography scale, raised borders,\n`defaultColor` and the four state roles (`focusColor`, `selectedColor`, `hoverColor`,\n`pressedColor`) belong to `Theme.designTokens`; colors remain CSS variables and can be\noverridden directly. `ThemeState.defaultColor` exposes the active role. Kit chrome should\nresolve omitted `color` props with `useDefaultColor`.\n";
1
+ export declare const themeDescription = "\n# Theme\n\n`Theme` owns global theme selection, runtime design tokens, shared overlay state, and theme\ntransitions. Wrap the application once and use the `ThemeState` received by the children snippet.\nComponents below it read the same state with `useTheme()` from `entasis/theme`, called during\ncomponent initialisation; it throws when no `Theme` is above. For a palette computed at runtime,\nsee `generateColorPalette` in `entasis/color-palette`.\n\n## Runtime design tokens\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme, type ThemeDesignTokenMap } from 'entasis/theme';\n\n\tlet spacing = $state<'small' | 'normal' | 'large'>('normal');\n\tconst designTokens = $derived({\n\t\tlight: {\n\t\t\tspacing,\n\t\t\tspacingScale: { xs: 1, sm: 1.5, md: 2, lg: 3, xl: 4 },\n\t\t\tradius: 'normal',\n\t\t\ttypeScale: 'default',\n\t\t\traisedWithBorder: true,\n\t\t\tdefaultColor: 'neutral'\n\t\t},\n\t\tdark: {\n\t\t\tspacing,\n\t\t\tspacingScale: { xs: 1, sm: 1.5, md: 2, lg: 3, xl: 4 },\n\t\t\tradius: 'small',\n\t\t\ttypeScale: 'compact',\n\t\t\traisedWithBorder: false,\n\t\t\tdefaultColor: 'neutral'\n\t\t}\n\t} satisfies ThemeDesignTokenMap<readonly ['light', 'dark']>);\n</script>\n\n<Theme {designTokens} transition=\"radial-top-right\">\n\t{#snippet children(theme)}\n\t\t<button onclick={() => (spacing = spacing === 'small' ? 'large' : 'small')}>\n\t\t\tChange density\n\t\t</button>\n\t\t<button onclick={() => (theme.theme = theme.resolvedTheme === 'dark' ? 'light' : 'dark')}>\n\t\t\tToggle color scheme\n\t\t</button>\n\t{/snippet}\n</Theme>\n```\n\n`designTokens` is keyed by logical theme name and respects the `attribute` and `value` props.\nEleven presets ship as `themePresets` (`dense`, `compact`, `balanced`, `comfortable`, `spacious`,\n`sharp`, `rounded`, `display`, `editorial`, `glass`, `terminal`): `designTokens={{ light: themePresets.glass.tokens, dark: themePresets.glass.tokens }}`.\nChanging the controlled object updates already-rendered Tailwind utilities without rebuilding CSS.\n\n### ThemeDesignTokens\n\n- `spacing`: `'small' | 'normal' | 'large' | number`. Globally scales density.\n- `spacingScale`: partial overrides for the strictly increasing `xs`, `sm`, `md`, `lg`,\n and `xl` spacing multipliers. Defaults to 1/1.5/2/3/4.\n- `radius`: `'none' | 'subtile' | 'small' | 'normal' | 'large' | 'round' | number`.\n Controls take the full multiplier; surface steps (`lg` and up) stop at `large` (1.5\u00D7).\n- `typeScale`: `'compact' | 'default' | 'comfortable' | 'large' | TypeScaleOptions`.\n- `raisedWithBorder`: toggles the border used by `raised-*` utilities.\n- `defaultColor`: `Colors` role kit chrome inherits when a control omits `color`.\n Defaults to `neutral`. Set `primary` to restore an accent-colored kit. Compiles the\n current-color family (`--color`, `--color-readable`, muted/contrast/light/dark variants)\n and `--default-color` onto the theme selector. Do not set `data-color` on `html`.\n- `focusColor`, `selectedColor`, `hoverColor`, `pressedColor`: the four `Colors` **state\n roles**. They pin, for the whole theme, what a focus ring, a persistent selection and the\n transient hover/pressed layer look like, independently of the role of the control the state\n lands on. They compile `--color-focus`, `--color-selected` (plus its `-contrast`,\n `-readable` and `-muted-readable` companions), `--color-hover` and\n `--color-pressed` onto the theme selector. There is no `--color-selected-muted`: the soft\n fill is a translucent tint of `--color-selected` at `--state-selected-opacity`, so it reads\n on any surface. None is declared at `:root`: every use site\n falls back to the matching current role (`ring-focus` is\n `var(--color-focus, var(--color))`, `bg-selected-muted` tints\n `var(--color-selected, var(--color))`, the state layer is\n `var(--color-hover, currentColor)` and on `:active`\n `var(--color-pressed, var(--color-hover, currentColor))`), so leaving them unset changes\n nothing and `data-color` keeps moving the states with `--color`. Theme-level only: there is\n no per-component override. An unknown role throws.\n\nComponent-level density remains a local variant. It selects utility classes whose values inherit\nthe active global spacing token.\n\nGenerated interfaces should use the public `xs | sm | md | lg | xl` vocabulary through component\nprops and named gap/padding utilities. `micro` and `layout-*` are internal recipe tokens. Prefer\nparent-owned gaps over child margins; do not emit arbitrary spacing or unsupported radius values.\n\n## Theme selection\n\nThe selection props wrap `svelte-themes`: `themes`, `defaultTheme`, `forcedTheme`,\n`systemTheme`, `syncColorScheme`, `transitionOnChange`, `storageKey`, `attribute`,\n`value`, and `colorScheme`. The default themes are light and dark, with system selection\nenabled. `systemTheme`, `syncColorScheme`, and `transitionOnChange` all default to\n`true`; they map onto the library's `enableSystem`, `enableColorScheme`, and\n`disableTransitionOnChange` options.\n\n`ThemeState` exposes `theme`, `resolvedTheme`, `themes`, and `systemTheme`. Assign\n`theme.theme` to switch themes. The optional `transition` prop applies a named view transition;\nunsupported browsers and reduced-motion users switch instantly.\n\n`spinnerVariant` sets the global default spinner animation. The children snippet is required.\n\n## Motion tokens\n\nMotion is a token scale like spacing and radius: five duration steps and four easing roles.\n`motion` retunes them app-wide; an omitted token keeps its default.\n\n| Duration | Default | | Easing role | Default |\n| ---------- | ------- | --- | ------------ | ------------- |\n| `instant` | 0ms | | `standard` | `cubicInOut` |\n| `fast` | 100ms | | `enter` | `cubicOut` |\n| `normal` | 200ms | | `exit` | `cubicIn` |\n| `slow` | 300ms | | `emphasized` | `backOut` |\n| `slower` | 500ms | | | |\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme motion={{ duration: { normal: 150, slow: 260 }, easing: { standard: 'quintOut' } }}>\n\t{@render children()}\n</Theme>\n```\n\nThe Tailwind plugin emits the same scale as CSS variables on `html` (`--duration-normal`,\n`--ease-standard`, ...) plus the matching `duration-*` / `ease-*` utilities, so CSS transitions\nand Svelte transitions read one set of numbers. The `motion` prop rewrites those variables on\n`html` at runtime and `designTokens.motion` rewrites them again per theme, layered over the prop;\n`ThemeState.motion` resolves through the same two rungs, so the utilities and the presets never\ndisagree. `ThemeState.transition` is a deprecated alias for its `normal` duration and `standard`\neasing. Reduced motion resolves every duration to 0 and collapses the `--duration-*` variables via\nthe `data-entasis-reduce-motion` attribute on `html`.\n\nComponents keep their own transition in a reserved `motion` slot on their theme, so the `theme`\nprop covers motion as well as classes:\n\n```svelte\n<script lang=\"ts\">\n\timport { Dialog } from 'entasis/dialog';\n</script>\n\n<Dialog theme={{ motion: { duration: 'fast', easing: 'emphasized' } }} title=\"Quick\">Body</Dialog>\n```\n\n## Component theme registry\n\n`components` sets app-wide component theme defaults without a wrapper component per component:\nit is keyed by theme name (`dialog`, `button`, ...) and each entry takes the same slots as that\ncomponent's `theme` prop, the `motion` slot included. A `set<Component>Theme` call in a subtree\nbeats the registry, and an instance `theme` prop beats both \u2014 per slot: each rung layers on the one\nbelow it, so a subtree that restyles one slot keeps the registry's others.\n\n```svelte\n<script lang=\"ts\">\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme\n\tcomponents={{\n\t\tdialog: { motion: { duration: 'fast' }, content: { base: 'rounded-2xl' } },\n\t\tbutton: { root: { base: 'tracking-wide' } }\n\t}}\n>\n\t{@render children()}\n</Theme>\n```\n\n## Reduced motion\n\n`reduceMotion` forces reduced motion on (`true`) or off (`false`) for every entasis animation,\noverriding the OS `prefers-reduced-motion` setting; omit it to follow the OS. The live result is\nexposed as `ThemeState.preferReducesMotion` (reactive, so it updates when the OS setting changes)\nand mirrored as a `data-entasis-reduce-motion` attribute on `html` for CSS-only animations.\n\n```svelte\n<script>\n\timport { Theme } from 'entasis/theme';\n\n\tlet { children } = $props();\n</script>\n\n<Theme reduceMotion>{@render children()}</Theme>\n```\n\n## Build-time boundary\n\nThe Tailwind plugin still generates color palettes and registers utility names, variants,\nkeyframes, and spinner CSS. Spacing, radius, typography scale, raised borders,\n`defaultColor` and the four state roles (`focusColor`, `selectedColor`, `hoverColor`,\n`pressedColor`) belong to `Theme.designTokens`; colors remain CSS variables and can be\noverridden directly. `ThemeState.defaultColor` exposes the active role. Kit chrome should\nresolve omitted `color` props with `useDefaultColor`.\n";
@@ -3,6 +3,9 @@ export const themeDescription = `
3
3
 
4
4
  \`Theme\` owns global theme selection, runtime design tokens, shared overlay state, and theme
5
5
  transitions. Wrap the application once and use the \`ThemeState\` received by the children snippet.
6
+ Components below it read the same state with \`useTheme()\` from \`entasis/theme\`, called during
7
+ component initialisation; it throws when no \`Theme\` is above. For a palette computed at runtime,
8
+ see \`generateColorPalette\` in \`entasis/color-palette\`.
6
9
 
7
10
  ## Runtime design tokens
8
11
 
@@ -112,6 +112,10 @@ export declare class ThemeState extends ThemeState_base {
112
112
  addEventListener: <E extends Events>(event: E, callback: (event: EventPayload[E]) => void) => () => void;
113
113
  addEventListenerOnMount: <E extends Events>(event: E, callback: (event: EventPayload[E]) => void) => void;
114
114
  }
115
+ /**
116
+ * The nearest `<Theme>`'s state: color scheme, design tokens, breakpoints and the methods that
117
+ * change them. Call it during component initialisation, like any Svelte context read.
118
+ */
115
119
  export declare const useTheme: () => ThemeState;
116
120
  /** Resolve a control color against Theme `defaultColor`. Call inside `$derived`. */
117
121
  export declare const useDefaultColor: (color?: Colors) => Colors;
@@ -193,6 +193,10 @@ export class ThemeState extends createBindableStateClass() {
193
193
  });
194
194
  };
195
195
  }
196
+ /**
197
+ * The nearest `<Theme>`'s state: color scheme, design tokens, breakpoints and the methods that
198
+ * change them. Call it during component initialisation, like any Svelte context read.
199
+ */
196
200
  export const useTheme = () => {
197
201
  const theme = getContext('entasisTheme');
198
202
  // A missing provider used to surface as `undefined is not an object` from whichever call site
@@ -76,8 +76,6 @@
76
76
  {#if typeof trigger === 'function'}
77
77
  {@render trigger(attach)}
78
78
  {:else}
79
- {@const { content: triggerContent, ...buttonProps } = trigger}
80
- <Button {...buttonProps} {@attach attach}>
81
- {triggerContent}
82
- </Button>
79
+ {@const { content: triggerContent, children, ...buttonProps } = trigger}
80
+ <Button {...buttonProps} children={children ?? triggerContent} {@attach attach} />
83
81
  {/if}
@@ -1,6 +1,7 @@
1
1
  import { useTheme } from '../Theme/theme.state.svelte.js';
2
2
  import { useHoverAction } from '../../utils/useHoverAction.svelte.js';
3
3
  import { on } from 'svelte/events';
4
+ const FOCUSABLE = 'a[href], button, input, select, textarea, summary, [tabindex], [contenteditable]:not([contenteditable="false"])';
4
5
  export const tooltip = (props) => {
5
6
  const theme = useTheme();
6
7
  let refElement = null;
@@ -37,6 +38,10 @@ export const tooltip = (props) => {
37
38
  };
38
39
  return (ref) => {
39
40
  refElement = ref;
41
+ // Keyboard users reach the tooltip by focusing its trigger, so an element the browser
42
+ // cannot focus (an icon, a badge, a truncated label) joins the tab order.
43
+ if (!ref.matches(FOCUSABLE))
44
+ ref.tabIndex = 0;
40
45
  const off = hoverAction.reference?.(ref);
41
46
  // Keyboard users get the tooltip on focus; screen readers get it via aria-describedby.
42
47
  const offFocus = on(ref, 'focusin', () => show(ref));
@@ -1 +1 @@
1
- export declare const tooltipDescription = "\n# Tooltip\n\nContextual information shown on hover or keyboard focus. Two forms share one surface:\n\n- `<Tooltip>` \u2014 a component with a `trigger` prop, like every other overlay.\n- `tooltip()` \u2014 the underlying attachment, for elements you already render yourself.\n\nBoth are rendered by the single tooltip surface that `<Theme>` mounts (`TooltipHost`).\n\n## Basic Usage\n\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Click to submit\" trigger={{ content: 'Submit', variant: 'outline' }} />\n```\n\n## Props\n\n- **content**: string | Snippet (required) - Tooltip body\n- **trigger**: Snippet<[Attachment<HTMLElement>]> | ButtonProps & { content?: string } (required) -\n A snippet receives the tooltip attachment and spreads it on its own element; Button props render\n a Button carrying it\n- **open**: boolean (default: false) - Shows the tooltip without hover or focus; bindable\n- **defaultOpen**: boolean (default: false) - Initial open state when `open` is not provided\n- **onOpenChange**: (open: boolean) => void - Called whenever the tooltip becomes visible or hidden,\n hover and focus included\n- **position**: Placement (default: 'top') - Tooltip position relative to the trigger\n - Options: 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'\n- **size**: 'small' | 'normal' | 'large' (default: 'normal') - Visual size\n- **color**: Colors (default: 'neutral') - Color theme\n- **variant**: 'solid' | 'outline' | 'soft' (default: 'solid') - Visual style matching Chip\n- **delay**: number (default: 400) - Delay in ms before showing tooltip; zero shows immediately\n- **offset**: number - Distance from the trigger in pixels\n- **class**: string - Additional CSS classes\n- **transition**: FSOProps - Custom transition configuration\n- **theme**: TooltipThemeProps - Per-instance theme overrides\n- **onAfterOpen**: () => void - Callback after the opening transition completes\n- **onAfterClose**: () => void - Callback after the closing transition completes\n\nEvery prop except `trigger`, `open`, `defaultOpen` and `onOpenChange` is also an option of the\n`tooltip()` attachment.\n\n## Examples\n\n### Button Trigger\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"This is helpful information\"\n\ttrigger={{ content: 'Hover me', variant: 'outline', color: 'neutral' }}\n/>\n```\n\n### Snippet Trigger\n```svelte\n<script lang=\"ts\">\n\timport type { Attachment } from 'svelte/attachments';\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n{#snippet helpTrigger(attach: Attachment<HTMLElement>)}\n\t<span class=\"underline\" {@attach attach}>What is this?</span>\n{/snippet}\n\n<Tooltip content=\"Anchored to any element you like\" trigger={helpTrigger} />\n```\n\n### Forced Open\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<!-- Useful for docs, screenshots and visual tests -->\n<Tooltip open content=\"Always visible\" trigger={{ content: 'Anchor', variant: 'outline' }} />\n```\n\n### Different Positions\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Top tooltip\" position=\"top\" trigger={{ content: 'Top' }} />\n<Tooltip content=\"Bottom tooltip\" position=\"bottom\" trigger={{ content: 'Bottom' }} />\n<Tooltip content=\"Left tooltip\" position=\"left\" trigger={{ content: 'Left' }} />\n<Tooltip content=\"Right tooltip\" position=\"right\" trigger={{ content: 'Right' }} />\n```\n\n### Different Colors\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Success!\" color=\"success\" trigger={{ content: 'Success' }} />\n<Tooltip content=\"Warning!\" color=\"warning\" trigger={{ content: 'Warning' }} />\n<Tooltip content=\"Error!\" color=\"danger\" trigger={{ content: 'Error' }} />\n```\n\n### Custom Delay\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Quick tooltip\" delay={100} trigger={{ content: 'Quick (100ms)' }} />\n<Tooltip content=\"Slow tooltip\" delay={1000} trigger={{ content: 'Slow (1000ms)' }} />\n```\n\n### Different Sizes and Variants\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Small tooltip\" size=\"small\" trigger={{ content: 'Small' }} />\n<Tooltip content=\"Large tooltip\" size=\"large\" trigger={{ content: 'Large' }} />\n<Tooltip content=\"Outlined tooltip\" variant=\"outline\" trigger={{ content: 'Outline' }} />\n<Tooltip content=\"Soft tooltip\" variant=\"soft\" trigger={{ content: 'Soft' }} />\n```\n\n### With Snippet Content\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n{#snippet richContent()}\n\t<div class=\"p-2\">\n\t\t<strong>Pro Tip</strong>\n\t\t<p class=\"text-sm\">Use Ctrl+S to save</p>\n\t</div>\n{/snippet}\n\n<Tooltip content={richContent} trigger={{ content: 'Keyboard Shortcuts' }} />\n```\n\n### With Callbacks\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"Tracked tooltip\"\n\tonAfterOpen={() => console.log('Tooltip opened')}\n\tonAfterClose={() => console.log('Tooltip closed')}\n\ttrigger={{ content: 'Track me' }}\n/>\n```\n\n## The tooltip() attachment\n\nUse the attachment when the element already exists in your markup \u2014 icons, table cells, list rows,\ndisabled wrappers \u2014 or inside another component's internals.\n\n```svelte\n<script lang=\"ts\">\n\timport { tooltip } from 'entasis/tooltip';\n</script>\n\n<button {@attach tooltip({ content: 'Click to submit' })}> Submit </button>\n\n<!-- On icons or any non-interactive element -->\n<span {@attach tooltip({ content: 'More information', position: 'right' })}> \u24D8 </span>\n\n<!-- Disabled elements do not fire events, so wrap them -->\n<span {@attach tooltip({ content: 'Feature coming soon' })}>\n\t<button disabled>Disabled Button</button>\n</span>\n```\n\nThe `<Tooltip>` component hands this same attachment to a snippet trigger, so the two forms are\ninterchangeable.\n\n## Accessibility\n\n- Shows on pointer hover and on keyboard focus (`focusin` / `focusout` on the trigger element), so\n attach it to focusable elements for keyboard users\n- Dismissed on mouse leave or blur\n- Non-interactive (cannot be clicked)\n- Renders with `role=\"tooltip\"` and sets `aria-describedby` on the trigger while visible (any previous value is restored on hide)\n- Does not block content behind it\n\n## Notes\n\n- Only one tooltip shows at a time; an `open` tooltip hands the surface over when another tooltip is\n hovered and reports that through `onOpenChange`\n- Automatically positions to stay in viewport using Floating UI\n- Uses smart delay: subsequent tooltips show instantly if within 400ms of previous\n- Brief content only (use Popover for interactive content)\n- The surface is a singleton (`TooltipHost`) rendered by `<Theme>`\n- Does not lock scroll or trap focus\n\n## Theme Customization\n\nThe Tooltip uses a theme object that can be customized using the `theme` prop or by setting a global theme.\n\n### Theme Structure\n\nThe theme object contains the following parts:\n- **root**: Main tooltip container styles\n\n### Theme Type Definition\n\n```typescript\nimport type { TooltipThemeProps } from 'entasis/tooltip';\n\n// Example theme customization\nconst customTheme: TooltipThemeProps = {\n root: {\n base: 'inline-flex w-fit items-center rounded-full border font-medium',\n size: {\n small: 'h-5 px-2 text-xs',\n normal: 'h-6 px-2.5 text-xs',\n large: 'h-7 px-3 text-sm'\n },\n\tcolor: {\n\t neutral: 'bg-neutral text-neutral-contrast',\n primary: 'bg-primary text-primary-contrast',\n danger: 'bg-danger text-danger-contrast',\n success: 'bg-success text-success-contrast',\n warning: 'bg-warning text-warning-contrast',\n\t info: 'bg-info text-info-contrast'\n\t},\n\tvariant: {\n\t solid: 'bg-color text-color-contrast',\n\t outline: 'border-color bg-transparent text-color-readable',\n\t soft: 'bg-color-muted text-color-muted-readable'\n }\n }\n};\n```\n\n### Available Variants\n\n**root**:\n- base: Base classes applied to all tooltips\n- Variants:\n - size: 'small' | 'normal' | 'large' - Controls text size and padding\n - color: 'primary' | 'secondary' | 'neutral' | 'danger' | 'success' | 'warning' | 'info' - Color scheme\n - variant: 'solid' | 'outline' | 'soft' - Matches Chip's visual variants\n\n### Usage Examples\n\n**Basic Theme Override**:\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"Custom tooltip\"\n\ttheme={{ root: { base: 'rounded-lg lift-4 border-2', size: { normal: 'px-3 py-2 text-sm' } } }}\n\ttrigger={{ content: 'Hover me' }}\n/>\n```\n\n**Color Customization**:\n```svelte\n<script lang=\"ts\">\n\timport { tooltip } from 'entasis/tooltip';\n</script>\n\n<button\n\t{@attach tooltip({\n\t\tcontent: 'Success!',\n\t\tcolor: 'success',\n\t\ttheme: { root: { color: { success: 'bg-green-500 text-white lift-3' } } }\n\t})}\n>\n\tSuccess Tooltip\n</button>\n```\n\n**Global Theme Setting**:\n```svelte\n<script lang=\"ts\">\n\timport { setTooltipTheme } from 'entasis/tooltip';\n\n\tsetTooltipTheme({\n\t\troot: {\n\t\t\tbase: 'rounded-md lift-4 backdrop-blur-sm',\n\t\t\tsize: { normal: 'px-3 py-1.5 text-sm' },\n\t\t\tcolor: { neutral: 'bg-gray-900 text-white', primary: 'bg-blue-500 text-white' }\n\t\t}\n\t});\n</script>\n```\n\n## Motion\n\n- **motion** theme slot: one preset (no variants) \u2014 a short fade-and-rise, `duration: 'fast'`.\n- Resolved by the tooltip surface and handed to the underlying Popover, so it replaces the\n popover preset.\n- Ladder: `<Theme components={{ tooltip: { motion } }}>` \u2192 `setTooltipTheme({ motion })` \u2192\n `theme.motion` \u2192 the tooltip's `transition` option. Reduced motion collapses it to 0.\n- The tooltip surface is a singleton rendered by `<Theme>`, so a `setTooltipTheme` call\n made *below* `<Theme>` never reaches it. Call it at or above the `<Theme>` boundary, or\n use the `<Theme components={{ tooltip }}>` registry, which always applies.\n";
1
+ export declare const tooltipDescription = "\n# Tooltip\n\nContextual information shown on hover or keyboard focus. Two forms share one surface:\n\n- `<Tooltip>` \u2014 a component with a `trigger` prop, like every other overlay.\n- `tooltip()` \u2014 the underlying attachment, for elements you already render yourself.\n\nBoth are rendered by the single tooltip surface that `<Theme>` mounts (`TooltipHost`).\n\n## Basic Usage\n\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Click to submit\" trigger={{ content: 'Submit', variant: 'outline' }} />\n```\n\n## Props\n\n- **content**: string | Snippet (required) - Tooltip body\n- **trigger**: Snippet<[Attachment<HTMLElement>]> | ButtonProps & { content?: string } (required) -\n A snippet receives the tooltip attachment and spreads it on its own element; an element the\n browser cannot focus (a span, an icon) gets `tabindex=\"0\"` so keyboard focus shows the tooltip.\n Button props render a Button carrying it; `children` (a string or a snippet) replaces\n `content` for a richer body\n- **open**: boolean (default: false) - Shows the tooltip without hover or focus; bindable\n- **defaultOpen**: boolean (default: false) - Initial open state when `open` is not provided\n- **onOpenChange**: (open: boolean) => void - Called whenever the tooltip becomes visible or hidden,\n hover and focus included\n- **position**: Placement (default: 'top') - Tooltip position relative to the trigger\n - Options: 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'\n- **size**: 'small' | 'normal' | 'large' (default: 'normal') - Visual size\n- **color**: Colors (default: 'neutral') - Color theme\n- **variant**: 'solid' | 'outline' | 'soft' (default: 'solid') - Visual style matching Chip\n- **delay**: number (default: 400) - Delay in ms before showing tooltip; zero shows immediately\n- **offset**: number - Distance from the trigger in pixels\n- **class**: string - Additional CSS classes\n- **transition**: FSOProps - Custom transition configuration\n- **theme**: TooltipThemeProps - Per-instance theme overrides\n- **onAfterOpen**: () => void - Callback after the opening transition completes\n- **onAfterClose**: () => void - Callback after the closing transition completes\n\nEvery prop except `trigger`, `open`, `defaultOpen` and `onOpenChange` is also an option of the\n`tooltip()` attachment.\n\n## Examples\n\n### Button Trigger\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"This is helpful information\"\n\ttrigger={{ content: 'Hover me', variant: 'outline', color: 'neutral' }}\n/>\n```\n\n### Snippet Trigger\n```svelte\n<script lang=\"ts\">\n\timport type { Attachment } from 'svelte/attachments';\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n{#snippet helpTrigger(attach: Attachment<HTMLElement>)}\n\t<span class=\"underline\" {@attach attach}>What is this?</span>\n{/snippet}\n\n<Tooltip content=\"Anchored to any element you like\" trigger={helpTrigger} />\n```\n\n### Forced Open\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<!-- Useful for docs, screenshots and visual tests -->\n<Tooltip open content=\"Always visible\" trigger={{ content: 'Anchor', variant: 'outline' }} />\n```\n\n### Different Positions\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Top tooltip\" position=\"top\" trigger={{ content: 'Top' }} />\n<Tooltip content=\"Bottom tooltip\" position=\"bottom\" trigger={{ content: 'Bottom' }} />\n<Tooltip content=\"Left tooltip\" position=\"left\" trigger={{ content: 'Left' }} />\n<Tooltip content=\"Right tooltip\" position=\"right\" trigger={{ content: 'Right' }} />\n```\n\n### Different Colors\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Success!\" color=\"success\" trigger={{ content: 'Success' }} />\n<Tooltip content=\"Warning!\" color=\"warning\" trigger={{ content: 'Warning' }} />\n<Tooltip content=\"Error!\" color=\"danger\" trigger={{ content: 'Error' }} />\n```\n\n### Custom Delay\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Quick tooltip\" delay={100} trigger={{ content: 'Quick (100ms)' }} />\n<Tooltip content=\"Slow tooltip\" delay={1000} trigger={{ content: 'Slow (1000ms)' }} />\n```\n\n### Different Sizes and Variants\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip content=\"Small tooltip\" size=\"small\" trigger={{ content: 'Small' }} />\n<Tooltip content=\"Large tooltip\" size=\"large\" trigger={{ content: 'Large' }} />\n<Tooltip content=\"Outlined tooltip\" variant=\"outline\" trigger={{ content: 'Outline' }} />\n<Tooltip content=\"Soft tooltip\" variant=\"soft\" trigger={{ content: 'Soft' }} />\n```\n\n### With Snippet Content\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n{#snippet richContent()}\n\t<div class=\"p-2\">\n\t\t<strong>Pro Tip</strong>\n\t\t<p class=\"text-sm\">Use Ctrl+S to save</p>\n\t</div>\n{/snippet}\n\n<Tooltip content={richContent} trigger={{ content: 'Keyboard Shortcuts' }} />\n```\n\n### With Callbacks\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"Tracked tooltip\"\n\tonAfterOpen={() => console.log('Tooltip opened')}\n\tonAfterClose={() => console.log('Tooltip closed')}\n\ttrigger={{ content: 'Track me' }}\n/>\n```\n\n## The tooltip() attachment\n\nUse the attachment when the element already exists in your markup \u2014 icons, table cells, list rows,\ndisabled wrappers \u2014 or inside another component's internals.\n\n```svelte\n<script lang=\"ts\">\n\timport { tooltip } from 'entasis/tooltip';\n</script>\n\n<button {@attach tooltip({ content: 'Click to submit' })}> Submit </button>\n\n<!-- On icons or any non-interactive element -->\n<span {@attach tooltip({ content: 'More information', position: 'right' })}> \u24D8 </span>\n\n<!-- Disabled elements do not fire events, so wrap them -->\n<span {@attach tooltip({ content: 'Feature coming soon' })}>\n\t<button disabled>Disabled Button</button>\n</span>\n```\n\nThe `<Tooltip>` component hands this same attachment to a snippet trigger, so the two forms are\ninterchangeable.\n\n## Accessibility\n\n- Shows on pointer hover and on keyboard focus (`focusin` / `focusout` on the trigger element), so\n attach it to focusable elements for keyboard users\n- Dismissed on mouse leave or blur\n- Non-interactive (cannot be clicked)\n- Renders with `role=\"tooltip\"` and sets `aria-describedby` on the trigger while visible (any previous value is restored on hide)\n- Does not block content behind it\n\n## Notes\n\n- Only one tooltip shows at a time; an `open` tooltip hands the surface over when another tooltip is\n hovered and reports that through `onOpenChange`\n- Automatically positions to stay in viewport using Floating UI\n- Uses smart delay: subsequent tooltips show instantly if within 400ms of previous\n- Brief content only (use Popover for interactive content)\n- The surface is a singleton (`TooltipHost`) rendered by `<Theme>`\n- Does not lock scroll or trap focus\n\n## Theme Customization\n\nThe Tooltip uses a theme object that can be customized using the `theme` prop or by setting a global theme.\n\n### Theme Structure\n\nThe theme object contains the following parts:\n- **root**: Main tooltip container styles\n\n### Theme Type Definition\n\n```typescript\nimport type { TooltipThemeProps } from 'entasis/tooltip';\n\n// Example theme customization\nconst customTheme: TooltipThemeProps = {\n root: {\n base: 'inline-flex w-fit items-center rounded-full border font-medium',\n size: {\n small: 'h-5 px-2 text-xs',\n normal: 'h-6 px-2.5 text-xs',\n large: 'h-7 px-3 text-sm'\n },\n\tcolor: {\n\t neutral: 'bg-neutral text-neutral-contrast',\n primary: 'bg-primary text-primary-contrast',\n danger: 'bg-danger text-danger-contrast',\n success: 'bg-success text-success-contrast',\n warning: 'bg-warning text-warning-contrast',\n\t info: 'bg-info text-info-contrast'\n\t},\n\tvariant: {\n\t solid: 'bg-color text-color-contrast',\n\t outline: 'border-color bg-transparent text-color-readable',\n\t soft: 'bg-color-muted text-color-muted-readable'\n }\n }\n};\n```\n\n### Available Variants\n\n**root**:\n- base: Base classes applied to all tooltips\n- Variants:\n - size: 'small' | 'normal' | 'large' - Controls text size and padding\n - color: 'primary' | 'secondary' | 'neutral' | 'danger' | 'success' | 'warning' | 'info' - Color scheme\n - variant: 'solid' | 'outline' | 'soft' - Matches Chip's visual variants\n\n### Usage Examples\n\n**Basic Theme Override**:\n```svelte\n<script lang=\"ts\">\n\timport { Tooltip } from 'entasis/tooltip';\n</script>\n\n<Tooltip\n\tcontent=\"Custom tooltip\"\n\ttheme={{ root: { base: 'rounded-lg lift-4 border-2', size: { normal: 'px-3 py-2 text-sm' } } }}\n\ttrigger={{ content: 'Hover me' }}\n/>\n```\n\n**Color Customization**:\n```svelte\n<script lang=\"ts\">\n\timport { tooltip } from 'entasis/tooltip';\n</script>\n\n<button\n\t{@attach tooltip({\n\t\tcontent: 'Success!',\n\t\tcolor: 'success',\n\t\ttheme: { root: { color: { success: 'bg-green-500 text-white lift-3' } } }\n\t})}\n>\n\tSuccess Tooltip\n</button>\n```\n\n**Global Theme Setting**:\n```svelte\n<script lang=\"ts\">\n\timport { setTooltipTheme } from 'entasis/tooltip';\n\n\tsetTooltipTheme({\n\t\troot: {\n\t\t\tbase: 'rounded-md lift-4 backdrop-blur-sm',\n\t\t\tsize: { normal: 'px-3 py-1.5 text-sm' },\n\t\t\tcolor: { neutral: 'bg-gray-900 text-white', primary: 'bg-blue-500 text-white' }\n\t\t}\n\t});\n</script>\n```\n\n## Motion\n\n- **motion** theme slot: one preset (no variants) \u2014 a short fade-and-rise, `duration: 'fast'`.\n- Resolved by the tooltip surface and handed to the underlying Popover, so it replaces the\n popover preset.\n- Ladder: `<Theme components={{ tooltip: { motion } }}>` \u2192 `setTooltipTheme({ motion })` \u2192\n `theme.motion` \u2192 the tooltip's `transition` option. Reduced motion collapses it to 0.\n- The tooltip surface is a singleton rendered by `<Theme>`, so a `setTooltipTheme` call\n made *below* `<Theme>` never reaches it. Call it at or above the `<Theme>` boundary, or\n use the `<Theme components={{ tooltip }}>` registry, which always applies.\n";
@@ -22,8 +22,10 @@ Both are rendered by the single tooltip surface that \`<Theme>\` mounts (\`Toolt
22
22
 
23
23
  - **content**: string | Snippet (required) - Tooltip body
24
24
  - **trigger**: Snippet<[Attachment<HTMLElement>]> | ButtonProps & { content?: string } (required) -
25
- A snippet receives the tooltip attachment and spreads it on its own element; Button props render
26
- a Button carrying it
25
+ A snippet receives the tooltip attachment and spreads it on its own element; an element the
26
+ browser cannot focus (a span, an icon) gets \`tabindex="0"\` so keyboard focus shows the tooltip.
27
+ Button props render a Button carrying it; \`children\` (a string or a snippet) replaces
28
+ \`content\` for a richer body
27
29
  - **open**: boolean (default: false) - Shows the tooltip without hover or focus; bindable
28
30
  - **defaultOpen**: boolean (default: false) - Initial open state when \`open\` is not provided
29
31
  - **onOpenChange**: (open: boolean) => void - Called whenever the tooltip becomes visible or hidden,
@@ -131,6 +131,7 @@ export const componentAliases: {
131
131
  'entasis/theme': string;
132
132
  'entasis/i18n': string;
133
133
  'entasis/tailwind-plugin': string;
134
+ 'entasis/color-palette': string;
134
135
  'entasis/types': string;
135
136
  'entasis/cva': string;
136
137
  'entasis/motion': string;
@@ -132,6 +132,7 @@ export const componentAliases = {
132
132
  'entasis/theme': './src/lib/components/Theme/index.ts',
133
133
  'entasis/i18n': './src/lib/i18n/index.ts',
134
134
  'entasis/tailwind-plugin': './src/lib/tailwind/index.ts',
135
+ 'entasis/color-palette': './src/lib/tailwind/palette.ts',
135
136
  'entasis/types': './src/lib/types/index.ts',
136
137
  'entasis/cva': './src/lib/utils/cva/index.ts',
137
138
  'entasis/motion': './src/lib/utils/motion/index.ts',
@@ -1070,7 +1070,7 @@ export declare const componentInventory: readonly [{
1070
1070
  readonly id: "data-table";
1071
1071
  readonly subpath: "entasis/data-table";
1072
1072
  readonly sourceIndex: "src/lib/components/DataTable/index.ts";
1073
- readonly exportedSymbols: readonly ["DataTable", "DataTableAggregation", "DataTableAlignment", "DataTableApi", "DataTableBooleanFilter", "DataTableBuiltInEditor", "DataTableCellCommit", "DataTableCellPayload", "DataTableCellRenderPayload", "DataTableClasses", "DataTableColumn", "DataTableColumnFilter", "DataTableCustomEditor", "DataTableCustomFilter", "DataTableDateEditor", "DataTableDateFilter", "DataTableEditor", "DataTableEditorPayload", "DataTableFilter", "DataTableFilterPayload", "DataTableHeaderPayload", "DataTableHeaderRenderPayload", "DataTableInteractionMode", "DataTableNumberEditor", "DataTableNumberFilter", "DataTableOption", "DataTablePaginationConfig", "DataTablePaginationState", "DataTablePinning", "DataTableProcessingMode", "DataTableProps", "DataTableRowPayload", "DataTableSearchConfig", "DataTableSelectEditor", "DataTableSelectFilter", "DataTableSelectionMode", "DataTableSorting", "DataTableState", "DataTableSwitchEditor", "DataTableTextEditor", "DataTableTextFilter", "DataTableTheme", "DataTableThemeProps", "DataTableToolbarPayload", "createDataTableColumnHelper", "createDataTableState", "dataTableDescription", "dataTableTheme", "setDataTableTheme", "useDataTableTheme"];
1073
+ readonly exportedSymbols: readonly ["DataTable", "DataTableAggregation", "DataTableAlignment", "DataTableApi", "DataTableBooleanFilter", "DataTableBuiltInEditor", "DataTableCellCommit", "DataTableCellPayload", "DataTableCellRenderPayload", "DataTableClasses", "DataTableColumn", "DataTableColumnFilter", "DataTableCustomEditor", "DataTableCustomFilter", "DataTableDateEditor", "DataTableDateFilter", "DataTableEditor", "DataTableEditorPayload", "DataTableFilter", "DataTableFilterPayload", "DataTableHeaderPayload", "DataTableHeaderRenderPayload", "DataTableInteractionMode", "DataTableNumberEditor", "DataTableNumberFilter", "DataTableOption", "DataTablePaginationConfig", "DataTablePaginationState", "DataTablePinning", "DataTableProcessingMode", "DataTableProps", "DataTableRowActivation", "DataTableRowPayload", "DataTableSearchConfig", "DataTableSelectEditor", "DataTableSelectFilter", "DataTableSelectionMode", "DataTableSorting", "DataTableState", "DataTableSwitchEditor", "DataTableTextEditor", "DataTableTextFilter", "DataTableTheme", "DataTableThemeProps", "DataTableToolbarPayload", "createDataTableColumnHelper", "createDataTableState", "dataTableDescription", "dataTableTheme", "setDataTableTheme", "useDataTableTheme"];
1074
1074
  readonly docs: readonly [{
1075
1075
  readonly id: "data-table";
1076
1076
  readonly route: "/components/data-table";
@@ -1518,7 +1518,7 @@ export declare const componentInventory: readonly [{
1518
1518
  readonly id: "popover";
1519
1519
  readonly subpath: "entasis/popover";
1520
1520
  readonly sourceIndex: "src/lib/components/Popover/index.ts";
1521
- readonly exportedSymbols: readonly ["Popover", "PopoverProps", "PopoverTheme", "PopoverThemeProps", "popoverTheme", "setPopoverTheme", "usePopoverContext", "usePopoverTheme"];
1521
+ readonly exportedSymbols: readonly ["Popover", "PopoverProps", "PopoverState", "PopoverTheme", "PopoverThemeProps", "popoverTheme", "setPopoverTheme", "usePopoverContext", "usePopoverTheme"];
1522
1522
  readonly docs: readonly [{
1523
1523
  readonly id: "popover";
1524
1524
  readonly route: "/components/popover";
@@ -1779,7 +1779,7 @@ export declare const componentInventory: readonly [{
1779
1779
  readonly id: "theme";
1780
1780
  readonly subpath: "entasis/theme";
1781
1781
  readonly sourceIndex: "src/lib/components/Theme/index.ts";
1782
- readonly exportedSymbols: readonly ["Breakpoint", "ContainerBreakpoint", "ResponsiveProps", "Theme", "ThemeDesignTokenMap", "ThemeDesignTokens", "ThemePreset", "ThemePresetName", "ThemePresetTokens", "ThemeProps", "ThemeRadius", "ThemeSpacing", "ThemeSpacingScale", "ThemeSpacingStep", "ThemeState", "ThemeTransition", "TypeScaleOptions", "TypeScalePreset", "TypeScaleRatio", "breakpoints", "containerBreakpoints", "defaultThemeSpacingScale", "focusRing", "resolveContainerBreakpoint", "resolveResponsive", "responsiveContainerClasses", "responsiveVariables", "selectedSoft", "selectedSolid", "themePresetNames", "themePresets", "themeTransitions", "typeScalePresets", "useDefaultColor"];
1782
+ readonly exportedSymbols: readonly ["Breakpoint", "ContainerBreakpoint", "ResponsiveProps", "Theme", "ThemeDesignTokenMap", "ThemeDesignTokens", "ThemePreset", "ThemePresetName", "ThemePresetTokens", "ThemeProps", "ThemeRadius", "ThemeSpacing", "ThemeSpacingScale", "ThemeSpacingStep", "ThemeState", "ThemeTransition", "TypeScaleOptions", "TypeScalePreset", "TypeScaleRatio", "breakpoints", "containerBreakpoints", "defaultThemeSpacingScale", "focusRing", "resolveContainerBreakpoint", "resolveResponsive", "responsiveContainerClasses", "responsiveVariables", "selectedSoft", "selectedSolid", "themePresetNames", "themePresets", "themeTransitions", "typeScalePresets", "useDefaultColor", "useTheme"];
1783
1783
  readonly docs: readonly [];
1784
1784
  readonly capabilities: readonly ["svelte", "component", "configuration"];
1785
1785
  readonly relatedComponents: readonly [];
@@ -1811,6 +1811,15 @@ export declare const componentInventory: readonly [{
1811
1811
  readonly capabilities: readonly ["tailwind", "theme-configuration", "color-palettes"];
1812
1812
  readonly relatedComponents: readonly ["theme", "tailwind-plugin"];
1813
1813
  readonly visibility: "public";
1814
+ }, {
1815
+ readonly id: "color-palette";
1816
+ readonly subpath: "entasis/color-palette";
1817
+ readonly sourceIndex: "src/lib/tailwind/palette.ts";
1818
+ readonly exportedSymbols: readonly ["ColorPalette", "ColorPaletteOptions", "ColorTheme", "generateColorPalette"];
1819
+ readonly docs: readonly [];
1820
+ readonly capabilities: readonly ["theme-configuration", "color-palettes"];
1821
+ readonly relatedComponents: readonly ["theme", "tailwind-plugin"];
1822
+ readonly visibility: "public";
1814
1823
  }, {
1815
1824
  readonly id: "types";
1816
1825
  readonly subpath: "entasis/types";
@@ -2009,6 +2018,7 @@ export declare const relatedComponents: {
2009
2018
  readonly i18n: readonly ["theme"];
2010
2019
  readonly 'tailwind-plugin': readonly ["theme"];
2011
2020
  readonly 'theme-tailwind-plugin': readonly ["theme", "tailwind-plugin"];
2021
+ readonly 'color-palette': readonly ["theme", "tailwind-plugin"];
2012
2022
  readonly types: readonly [];
2013
2023
  readonly cva: readonly ["theme"];
2014
2024
  readonly motion: readonly ["theme"];
@@ -2670,6 +2670,7 @@ export const componentInventory = [
2670
2670
  'DataTablePinning',
2671
2671
  'DataTableProcessingMode',
2672
2672
  'DataTableProps',
2673
+ 'DataTableRowActivation',
2673
2674
  'DataTableRowPayload',
2674
2675
  'DataTableSearchConfig',
2675
2676
  'DataTableSelectEditor',
@@ -3598,6 +3599,7 @@ export const componentInventory = [
3598
3599
  exportedSymbols: [
3599
3600
  'Popover',
3600
3601
  'PopoverProps',
3602
+ 'PopoverState',
3601
3603
  'PopoverTheme',
3602
3604
  'PopoverThemeProps',
3603
3605
  'popoverTheme',
@@ -4226,7 +4228,8 @@ export const componentInventory = [
4226
4228
  'themePresets',
4227
4229
  'themeTransitions',
4228
4230
  'typeScalePresets',
4229
- 'useDefaultColor'
4231
+ 'useDefaultColor',
4232
+ 'useTheme'
4230
4233
  ],
4231
4234
  docs: [],
4232
4235
  capabilities: ['svelte', 'component', 'configuration'],
@@ -4274,6 +4277,16 @@ export const componentInventory = [
4274
4277
  relatedComponents: ['theme', 'tailwind-plugin'],
4275
4278
  visibility: 'public'
4276
4279
  },
4280
+ {
4281
+ id: 'color-palette',
4282
+ subpath: 'entasis/color-palette',
4283
+ sourceIndex: 'src/lib/tailwind/palette.ts',
4284
+ exportedSymbols: ['ColorPalette', 'ColorPaletteOptions', 'ColorTheme', 'generateColorPalette'],
4285
+ docs: [],
4286
+ capabilities: ['theme-configuration', 'color-palettes'],
4287
+ relatedComponents: ['theme', 'tailwind-plugin'],
4288
+ visibility: 'public'
4289
+ },
4277
4290
  {
4278
4291
  id: 'types',
4279
4292
  subpath: 'entasis/types',
@@ -4547,6 +4560,7 @@ export const relatedComponents = {
4547
4560
  i18n: ['theme'],
4548
4561
  'tailwind-plugin': ['theme'],
4549
4562
  'theme-tailwind-plugin': ['theme', 'tailwind-plugin'],
4563
+ 'color-palette': ['theme', 'tailwind-plugin'],
4550
4564
  types: [],
4551
4565
  cva: ['theme'],
4552
4566
  motion: ['theme'],