@adea-ai/ui 0.71.1 → 0.71.3

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 (99) hide show
  1. package/dist/components/composites/appearance-editor/appearance-editor.js +1 -1
  2. package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
  3. package/dist/components/composites/stat/stat.d.ts.map +1 -1
  4. package/dist/components/composites/stat/stat.js +8 -8
  5. package/dist/components/composites/stat/stat.js.map +1 -1
  6. package/dist/components/composites/update-dialog/update-dialog.d.ts +7 -0
  7. package/dist/components/composites/update-dialog/update-dialog.d.ts.map +1 -1
  8. package/dist/components/composites/update-dialog/update-dialog.js +71 -26
  9. package/dist/components/composites/update-dialog/update-dialog.js.map +1 -1
  10. package/dist/components/conversation/internal/chat-composer-shell.js +1 -1
  11. package/dist/components/conversation/internal/chat-composer-shell.js.map +1 -1
  12. package/dist/components/conversation/message-composer.d.ts.map +1 -1
  13. package/dist/components/conversation/message-composer.js +1 -1
  14. package/dist/components/conversation/message-composer.js.map +1 -1
  15. package/dist/components/ui/alert/alert.d.ts +3 -1
  16. package/dist/components/ui/alert/alert.d.ts.map +1 -1
  17. package/dist/components/ui/alert/alert.js +18 -8
  18. package/dist/components/ui/alert/alert.js.map +1 -1
  19. package/dist/components/ui/badge/badge.js +4 -4
  20. package/dist/components/ui/badge/badge.js.map +1 -1
  21. package/dist/components/ui/context-menu/context-menu.d.ts.map +1 -1
  22. package/dist/components/ui/context-menu/context-menu.js +2 -2
  23. package/dist/components/ui/context-menu/context-menu.js.map +1 -1
  24. package/dist/components/ui/dialog/dialog.d.ts +17 -1
  25. package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
  26. package/dist/components/ui/dialog/dialog.js +120 -2
  27. package/dist/components/ui/dialog/dialog.js.map +1 -1
  28. package/dist/components/ui/diff-block/diff-block.js +2 -2
  29. package/dist/components/ui/diff-block/diff-block.js.map +1 -1
  30. package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts +3 -2
  31. package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts.map +1 -1
  32. package/dist/components/ui/dropdown-menu/dropdown-menu.js +5 -4
  33. package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
  34. package/dist/components/ui/entity-icon/entity-icon.d.ts +3 -3
  35. package/dist/components/ui/entity-icon/entity-icon.js +7 -7
  36. package/dist/components/ui/entity-icon/entity-icon.js.map +1 -1
  37. package/dist/components/ui/field/field.js +1 -1
  38. package/dist/components/ui/field/field.js.map +1 -1
  39. package/dist/components/ui/menubar/menubar.d.ts.map +1 -1
  40. package/dist/components/ui/menubar/menubar.js +2 -2
  41. package/dist/components/ui/menubar/menubar.js.map +1 -1
  42. package/dist/components/ui/modal-dialog/modal-dialog.d.ts +12 -2
  43. package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
  44. package/dist/components/ui/modal-dialog/modal-dialog.js +44 -27
  45. package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
  46. package/dist/components/ui/status-chip/status-chip.js +4 -4
  47. package/dist/components/ui/status-chip/status-chip.js.map +1 -1
  48. package/dist/lib/overlay.d.ts +2 -0
  49. package/dist/lib/overlay.d.ts.map +1 -1
  50. package/dist/lib/overlay.js +3 -1
  51. package/dist/lib/overlay.js.map +1 -1
  52. package/dist/lib/themes.d.ts +7 -0
  53. package/dist/lib/themes.d.ts.map +1 -1
  54. package/dist/lib/themes.js +22 -1
  55. package/dist/lib/themes.js.map +1 -1
  56. package/dist/lib/tokens.d.ts.map +1 -1
  57. package/dist/lib/tokens.js +4 -4
  58. package/dist/lib/tokens.js.map +1 -1
  59. package/dist/r/src/components/composites/appearance-editor/appearance-editor.tsx +1 -1
  60. package/dist/r/src/components/composites/stat/stat.tsx +5 -8
  61. package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +98 -26
  62. package/dist/r/src/components/conversation/internal/chat-composer-shell.tsx +1 -1
  63. package/dist/r/src/components/conversation/message-composer.tsx +3 -1
  64. package/dist/r/src/components/ui/alert/alert.tsx +20 -7
  65. package/dist/r/src/components/ui/badge/badge.tsx +4 -4
  66. package/dist/r/src/components/ui/context-menu/context-menu.tsx +2 -2
  67. package/dist/r/src/components/ui/dialog/dialog.tsx +204 -2
  68. package/dist/r/src/components/ui/diff-block/diff-block.tsx +4 -4
  69. package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +5 -4
  70. package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +7 -7
  71. package/dist/r/src/components/ui/field/field.tsx +1 -1
  72. package/dist/r/src/components/ui/menubar/menubar.tsx +2 -2
  73. package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +24 -2
  74. package/dist/r/src/components/ui/status-chip/status-chip.tsx +4 -4
  75. package/dist/r/src/lib/overlay.ts +4 -0
  76. package/dist/r/src/lib/themes.ts +29 -0
  77. package/dist/r/src/lib/tokens.ts +19 -4
  78. package/dist/r/src/styles/theme.css +10 -10
  79. package/package.json +2 -2
  80. package/src/components/composites/appearance-editor/appearance-editor.tsx +1 -1
  81. package/src/components/composites/stat/stat.tsx +5 -8
  82. package/src/components/composites/update-dialog/update-dialog.tsx +98 -26
  83. package/src/components/conversation/internal/chat-composer-shell.tsx +1 -1
  84. package/src/components/conversation/message-composer.tsx +3 -1
  85. package/src/components/ui/alert/alert.tsx +20 -7
  86. package/src/components/ui/badge/badge.tsx +4 -4
  87. package/src/components/ui/context-menu/context-menu.tsx +2 -2
  88. package/src/components/ui/dialog/dialog.tsx +204 -2
  89. package/src/components/ui/diff-block/diff-block.tsx +4 -4
  90. package/src/components/ui/dropdown-menu/dropdown-menu.tsx +5 -4
  91. package/src/components/ui/entity-icon/entity-icon.tsx +7 -7
  92. package/src/components/ui/field/field.tsx +1 -1
  93. package/src/components/ui/menubar/menubar.tsx +2 -2
  94. package/src/components/ui/modal-dialog/modal-dialog.tsx +24 -2
  95. package/src/components/ui/status-chip/status-chip.tsx +4 -4
  96. package/src/lib/overlay.ts +4 -0
  97. package/src/lib/themes.ts +29 -0
  98. package/src/lib/tokens.ts +19 -4
  99. package/src/styles/theme.css +10 -10
@@ -2,12 +2,130 @@ import { cn } from "../../../lib/utils.js";
2
2
  import { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from "../../../lib/overlay.js";
3
3
  import { className, createComponent, insert, memo, mergeProps, spread, template } from "solid-js/web";
4
4
  import { X } from "lucide-solid";
5
- import { Show, splitProps } from "solid-js";
5
+ import { Show, createRenderEffect, onCleanup, splitProps } from "solid-js";
6
6
  import { Dialog } from "@kobalte/core/dialog";
7
7
  //#region src/components/ui/dialog/dialog.tsx
8
8
  var _tmpl$ = /*#__PURE__*/ template(`<div>`);
9
9
  var _tmpl$2 = /*#__PURE__*/ template(`<div data-slot=dialog-header>`);
10
10
  var _tmpl$3 = /*#__PURE__*/ template(`<div data-slot=dialog-footer>`);
11
+ function canRestoreFocus(target) {
12
+ return target.isConnected && target !== document.body && target !== document.documentElement && !target.closest("[inert], [aria-hidden=\"true\"]") && !target.matches(":disabled") && target.getClientRects().length > 0;
13
+ }
14
+ function hasOtherOverlay(content, opener) {
15
+ return [...document.querySelectorAll("[role=\"dialog\"], [role=\"alertdialog\"]")].some((overlay) => overlay !== content && !content.contains(overlay) && !overlay.contains(opener) && !overlay.closest("[aria-hidden=\"true\"], [inert]") && overlay.getClientRects().length > 0);
16
+ }
17
+ /**
18
+ * Adds guarded opener capture and restoration to a Kobalte dialog content.
19
+ * Composed surfaces use this internal helper; it is omitted from the public
20
+ * dialog barrel so the restoration policy stays with the dialog components.
21
+ */
22
+ function createDialogFocusRestoration({ open, restoreFocusRef, onOpenAutoFocus: callerOnOpenAutoFocus, onCloseAutoFocus: callerOnCloseAutoFocus }) {
23
+ const focusCycles = /* @__PURE__ */ new WeakMap();
24
+ let activeFocusCycle;
25
+ let pendingOpener = null;
26
+ let pendingOpenerEligible = false;
27
+ createRenderEffect(() => {
28
+ if (!open() || typeof document === "undefined") {
29
+ pendingOpener = null;
30
+ pendingOpenerEligible = false;
31
+ return;
32
+ }
33
+ const active = restoreFocusRef?.() ?? document.activeElement;
34
+ pendingOpener = active instanceof HTMLElement ? active : null;
35
+ pendingOpenerEligible = active instanceof HTMLElement && canRestoreFocus(active);
36
+ });
37
+ const finishFocusCycle = (cycle) => {
38
+ if (cycle.frame !== void 0) window.cancelAnimationFrame(cycle.frame);
39
+ if (cycle.fallbackTimer !== void 0) window.clearTimeout(cycle.fallbackTimer);
40
+ cycle.observer?.disconnect();
41
+ document.removeEventListener("focusin", cycle.onFocusIn);
42
+ if (activeFocusCycle === cycle) activeFocusCycle = void 0;
43
+ };
44
+ const scheduleFocusRestore = (cycle) => {
45
+ if (cycle.frame !== void 0) return;
46
+ cycle.frame = window.requestAnimationFrame(() => {
47
+ cycle.frame = void 0;
48
+ const opener = cycle.opener;
49
+ const active = document.activeElement;
50
+ const focusIsAvailable = active === document.body || active === document.documentElement || active === cycle.content || active instanceof Node && cycle.content.contains(active);
51
+ if (activeFocusCycle !== cycle || !cycle.closed || cycle.focusMovedOutside || !opener || !opener.isConnected || opener.matches(":disabled") || opener.getClientRects().length === 0 || !focusIsAvailable || hasOtherOverlay(cycle.content, opener)) {
52
+ finishFocusCycle(cycle);
53
+ return;
54
+ }
55
+ if (opener.closest("[inert], [aria-hidden=\"true\"]")) return;
56
+ if (cycle.openerEligible && canRestoreFocus(opener)) opener.focus({ preventScroll: true });
57
+ finishFocusCycle(cycle);
58
+ });
59
+ };
60
+ const onOpenAutoFocus = (event) => {
61
+ const element = event.currentTarget;
62
+ if (element instanceof HTMLElement) {
63
+ if (activeFocusCycle) finishFocusCycle(activeFocusCycle);
64
+ const openerWasCaptured = pendingOpener !== null;
65
+ const opener = pendingOpener ?? document.activeElement;
66
+ const openerEligible = openerWasCaptured ? pendingOpenerEligible : opener instanceof HTMLElement && canRestoreFocus(opener);
67
+ pendingOpener = null;
68
+ pendingOpenerEligible = false;
69
+ const cycle = {
70
+ content: element,
71
+ opener: opener instanceof HTMLElement ? opener : null,
72
+ openerEligible,
73
+ closed: false,
74
+ focusMovedOutside: false,
75
+ closeAutoFocusScheduled: false,
76
+ onFocusIn: (focusEvent) => {
77
+ const target = focusEvent.target;
78
+ if (!(target instanceof HTMLElement) || target === document.body || target === document.documentElement || target === element || element.contains(target) || target === (opener instanceof HTMLElement ? opener : null)) return;
79
+ cycle.focusMovedOutside = true;
80
+ }
81
+ };
82
+ focusCycles.set(element, cycle);
83
+ activeFocusCycle = cycle;
84
+ document.addEventListener("focusin", cycle.onFocusIn);
85
+ }
86
+ callerOnOpenAutoFocus?.(event);
87
+ };
88
+ const onCloseAutoFocus = (event) => {
89
+ const element = event.currentTarget;
90
+ const cycle = element instanceof HTMLElement ? focusCycles.get(element) : void 0;
91
+ callerOnCloseAutoFocus?.(event);
92
+ if (!cycle) return;
93
+ cycle.closed = true;
94
+ if (event.defaultPrevented) {
95
+ finishFocusCycle(cycle);
96
+ return;
97
+ }
98
+ if (cycle.fallbackTimer !== void 0) {
99
+ window.clearTimeout(cycle.fallbackTimer);
100
+ cycle.fallbackTimer = void 0;
101
+ }
102
+ cycle.closeAutoFocusScheduled = true;
103
+ cycle.observer = new MutationObserver(() => scheduleFocusRestore(cycle));
104
+ cycle.observer.observe(document.body, {
105
+ attributes: true,
106
+ attributeFilter: ["aria-hidden", "inert"],
107
+ childList: true,
108
+ subtree: true
109
+ });
110
+ scheduleFocusRestore(cycle);
111
+ };
112
+ onCleanup(() => {
113
+ const cycle = activeFocusCycle;
114
+ if (!cycle) return;
115
+ cycle.closed = true;
116
+ queueMicrotask(() => {
117
+ if (cycle.closeAutoFocusScheduled) return;
118
+ cycle.fallbackTimer = window.setTimeout(() => {
119
+ cycle.fallbackTimer = void 0;
120
+ if (!cycle.closeAutoFocusScheduled) finishFocusCycle(cycle);
121
+ }, 0);
122
+ });
123
+ });
124
+ return {
125
+ onOpenAutoFocus,
126
+ onCloseAutoFocus
127
+ };
128
+ }
11
129
  /**
12
130
  * Dialog.
13
131
  *
@@ -120,6 +238,6 @@ function DialogClose(props) {
120
238
  } }, rest));
121
239
  }
122
240
  //#endregion
123
- export { Dialog$1 as Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger };
241
+ export { Dialog$1 as Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, createDialogFocusRestoration };
124
242
 
125
243
  //# sourceMappingURL=dialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.js","names":["Dialog","KobalteDialog","X","ComponentProps","JSX","Show","splitProps","overlayMotion","overlayPositioner","overlayScrim","overlaySurface","cn","props","_$createComponent","DialogTrigger","Trigger","DialogPortal","Portal","DialogOverlay","Overlay","local","rest","_$mergeProps","class","DialogContentProps","Content","closeButton","Element","DialogContent","children","_el$","_tmpl$","_$className","_$insert","_$memo","when","CloseButton","DialogHeader","_el$2","_tmpl$2","_$spread","DialogFooter","_el$3","_tmpl$3","DialogTitle","Title","DialogDescription","Description","DialogCloseButton","DialogClose","Dialog","_$createComponent","KobalteDialog","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dialog/dialog.tsx"],"sourcesContent":["import { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { X } from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * Dialog.\n *\n * A modal surface for a decision or a short task. `Dialog.Portal` keeps the\n * panel out of the app's stacking and overflow contexts, `Dialog.Overlay`\n * dims what is behind it, and Kobalte handles the focus trap, the escape key,\n * scroll locking and returning focus to the trigger on close.\n *\n * The close button is part of the content rather than optional, because every\n * modal needs a way out that is not the keyboard. A dialog whose only exit is\n * Escape is a trap for anyone using a pointer.\n */\nexport function Dialog(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function DialogPortal(props: ComponentProps<typeof KobalteDialog.Portal>) {\n return <KobalteDialog.Portal {...props} />\n}\n\nexport function DialogOverlay(props: ComponentProps<typeof KobalteDialog.Overlay>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Overlay\n class={cn(\n overlayScrim,\n 'data-expanded:animate-in data-expanded:fade-in-0 data-closed:animate-out data-closed:fade-out-0',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type DialogContentProps = ComponentProps<typeof KobalteDialog.Content> & {\n /**\n * Replaces the default close button. Pass `false` to remove it — only for a\n * dialog that cannot be dismissed (an update that must finish); anything the\n * user can escape from needs the button.\n */\n closeButton?: JSX.Element | false\n}\n\nexport function DialogContent(props: DialogContentProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'closeButton'])\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <div class={overlayPositioner}>\n <KobalteDialog.Content\n class={cn(overlaySurface, overlayMotion, 'grid w-full max-w-lg gap-4 p-5', local.class)}\n {...rest}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n class={cn(\n 'absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground',\n 'transition-colors ease-out hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle outline-none'\n )}\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialog.Content>\n </div>\n </KobalteDialog.Portal>\n )\n}\n\nexport function DialogHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-header\"\n class={cn('flex flex-col gap-1.5 pe-6 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-footer\"\n class={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title\n class={cn('text-base leading-none font-semibold tracking-tight', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function DialogCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n\n/**\n * The close control, unstyled and polymorphic — for a footer's text \"Cancel\" or\n * \"Close\", which is a different control from the corner icon `DialogCloseButton`\n * draws. Take it as `as={Button}` so it carries the button's variants rather than\n * a copied class string.\n */\nexport function DialogClose(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dialog.js","names":["Dialog","KobalteDialog","X","Accessor","ComponentProps","JSX","createRenderEffect","onCleanup","Show","splitProps","overlayMotion","overlayPositioner","overlayScrim","overlaySurface","cn","FocusCycle","content","HTMLElement","opener","openerEligible","closed","focusMovedOutside","closeAutoFocusScheduled","frame","fallbackTimer","observer","MutationObserver","onFocusIn","event","FocusEvent","canRestoreFocus","target","isConnected","document","body","documentElement","closest","matches","getClientRects","length","hasOtherOverlay","querySelectorAll","some","overlay","contains","DialogFocusRestorationOptions","open","restoreFocusRef","onOpenAutoFocus","Content","onCloseAutoFocus","createDialogFocusRestoration","callerOnOpenAutoFocus","callerOnCloseAutoFocus","focusCycles","WeakMap","activeFocusCycle","pendingOpener","pendingOpenerEligible","active","activeElement","finishFocusCycle","cycle","undefined","window","cancelAnimationFrame","clearTimeout","disconnect","removeEventListener","scheduleFocusRestore","requestAnimationFrame","focusIsAvailable","Node","focus","preventScroll","Event","element","currentTarget","openerWasCaptured","focusEvent","set","addEventListener","get","defaultPrevented","observe","attributes","attributeFilter","childList","subtree","queueMicrotask","setTimeout","props","_$createComponent","DialogTrigger","Trigger","DialogPortal","Portal","DialogOverlay","Overlay","local","rest","_$mergeProps","class","DialogContentProps","closeButton","Element","DialogContent","children","_el$","_tmpl$","_$className","_$insert","_$memo","when","CloseButton","DialogHeader","_el$2","_tmpl$2","_$spread","DialogFooter","_el$3","_tmpl$3","DialogTitle","Title","DialogDescription","Description","DialogCloseButton","DialogClose","Dialog","_$createComponent","KobalteDialog","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dialog/dialog.tsx"],"sourcesContent":["import { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { X } from 'lucide-solid'\nimport type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { createRenderEffect, onCleanup, Show, splitProps } from 'solid-js'\nimport { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\ntype FocusCycle = {\n content: HTMLElement\n opener: HTMLElement | null\n openerEligible: boolean\n closed: boolean\n focusMovedOutside: boolean\n closeAutoFocusScheduled: boolean\n frame?: number\n fallbackTimer?: number\n observer?: MutationObserver\n onFocusIn: (event: FocusEvent) => void\n}\n\nfunction canRestoreFocus(target: HTMLElement): boolean {\n return (\n target.isConnected &&\n target !== document.body &&\n target !== document.documentElement &&\n !target.closest('[inert], [aria-hidden=\"true\"]') &&\n !target.matches(':disabled') &&\n target.getClientRects().length > 0\n )\n}\n\nfunction hasOtherOverlay(content: HTMLElement, opener: HTMLElement): boolean {\n return [...document.querySelectorAll<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]')].some(\n (overlay) =>\n overlay !== content &&\n !content.contains(overlay) &&\n !overlay.contains(opener) &&\n !overlay.closest('[aria-hidden=\"true\"], [inert]') &&\n overlay.getClientRects().length > 0\n )\n}\n\ntype DialogFocusRestorationOptions = {\n open: Accessor<boolean>\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n onOpenAutoFocus?: ComponentProps<typeof KobalteDialog.Content>['onOpenAutoFocus']\n onCloseAutoFocus?: ComponentProps<typeof KobalteDialog.Content>['onCloseAutoFocus']\n}\n\n/**\n * Adds guarded opener capture and restoration to a Kobalte dialog content.\n * Composed surfaces use this internal helper; it is omitted from the public\n * dialog barrel so the restoration policy stays with the dialog components.\n */\nexport function createDialogFocusRestoration({\n open,\n restoreFocusRef,\n onOpenAutoFocus: callerOnOpenAutoFocus,\n onCloseAutoFocus: callerOnCloseAutoFocus,\n}: DialogFocusRestorationOptions) {\n const focusCycles = new WeakMap<HTMLElement, FocusCycle>()\n let activeFocusCycle: FocusCycle | undefined\n let pendingOpener: HTMLElement | null = null\n let pendingOpenerEligible = false\n\n createRenderEffect(() => {\n if (!open() || typeof document === 'undefined') {\n pendingOpener = null\n pendingOpenerEligible = false\n return\n }\n const active = restoreFocusRef?.() ?? document.activeElement\n pendingOpener = active instanceof HTMLElement ? active : null\n pendingOpenerEligible = active instanceof HTMLElement && canRestoreFocus(active)\n })\n\n const finishFocusCycle = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) window.cancelAnimationFrame(cycle.frame)\n if (cycle.fallbackTimer !== undefined) window.clearTimeout(cycle.fallbackTimer)\n cycle.observer?.disconnect()\n document.removeEventListener('focusin', cycle.onFocusIn)\n if (activeFocusCycle === cycle) activeFocusCycle = undefined\n }\n\n const scheduleFocusRestore = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) return\n cycle.frame = window.requestAnimationFrame(() => {\n cycle.frame = undefined\n const opener = cycle.opener\n const active = document.activeElement\n const focusIsAvailable =\n active === document.body ||\n active === document.documentElement ||\n active === cycle.content ||\n (active instanceof Node && cycle.content.contains(active))\n if (\n activeFocusCycle !== cycle ||\n !cycle.closed ||\n cycle.focusMovedOutside ||\n !opener ||\n !opener.isConnected ||\n opener.matches(':disabled') ||\n opener.getClientRects().length === 0 ||\n !focusIsAvailable ||\n hasOtherOverlay(cycle.content, opener)\n ) {\n finishFocusCycle(cycle)\n return\n }\n\n // Inert and aria-hidden are removed by the dialog's containment cleanup.\n // Wait for that cleanup before returning focus to the original control.\n if (opener.closest('[inert], [aria-hidden=\"true\"]')) return\n if (cycle.openerEligible && canRestoreFocus(opener)) {\n opener.focus({ preventScroll: true })\n }\n finishFocusCycle(cycle)\n })\n }\n\n const onOpenAutoFocus = (event: Event) => {\n const element = event.currentTarget\n if (element instanceof HTMLElement) {\n if (activeFocusCycle) finishFocusCycle(activeFocusCycle)\n\n const openerWasCaptured = pendingOpener !== null\n const opener = pendingOpener ?? document.activeElement\n const openerEligible = openerWasCaptured\n ? pendingOpenerEligible\n : opener instanceof HTMLElement && canRestoreFocus(opener)\n pendingOpener = null\n pendingOpenerEligible = false\n const cycle: FocusCycle = {\n content: element,\n opener: opener instanceof HTMLElement ? opener : null,\n openerEligible,\n closed: false,\n focusMovedOutside: false,\n closeAutoFocusScheduled: false,\n onFocusIn: (focusEvent) => {\n const target = focusEvent.target\n if (\n !(target instanceof HTMLElement) ||\n target === document.body ||\n target === document.documentElement ||\n target === element ||\n element.contains(target) ||\n target === (opener instanceof HTMLElement ? opener : null)\n ) {\n return\n }\n cycle.focusMovedOutside = true\n },\n }\n focusCycles.set(element, cycle)\n activeFocusCycle = cycle\n document.addEventListener('focusin', cycle.onFocusIn)\n }\n callerOnOpenAutoFocus?.(event)\n }\n\n const onCloseAutoFocus = (event: Event) => {\n const element = event.currentTarget\n const cycle = element instanceof HTMLElement ? focusCycles.get(element) : undefined\n callerOnCloseAutoFocus?.(event)\n\n if (!cycle) return\n cycle.closed = true\n\n // A caller that prevents Kobalte's close autofocus owns the focus decision.\n if (event.defaultPrevented) {\n finishFocusCycle(cycle)\n return\n }\n\n if (cycle.fallbackTimer !== undefined) {\n window.clearTimeout(cycle.fallbackTimer)\n cycle.fallbackTimer = undefined\n }\n cycle.closeAutoFocusScheduled = true\n cycle.observer = new MutationObserver(() => scheduleFocusRestore(cycle))\n cycle.observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['aria-hidden', 'inert'],\n childList: true,\n subtree: true,\n })\n scheduleFocusRestore(cycle)\n }\n\n onCleanup(() => {\n const cycle = activeFocusCycle\n if (!cycle) return\n cycle.closed = true\n\n // Kobalte dispatches unmount autofocus from a timer. This fallback only\n // releases the scoped focus listener if the content did not dispatch it.\n queueMicrotask(() => {\n if (cycle.closeAutoFocusScheduled) return\n cycle.fallbackTimer = window.setTimeout(() => {\n cycle.fallbackTimer = undefined\n if (!cycle.closeAutoFocusScheduled) finishFocusCycle(cycle)\n }, 0)\n })\n })\n\n return { onOpenAutoFocus, onCloseAutoFocus }\n}\n\n/**\n * Dialog.\n *\n * A modal surface for a decision or a short task. `Dialog.Portal` keeps the\n * panel out of the app's stacking and overflow contexts, `Dialog.Overlay`\n * dims what is behind it, and Kobalte handles the focus trap, the escape key,\n * scroll locking and returning focus to the trigger on close.\n *\n * The close button is part of the content rather than optional, because every\n * modal needs a way out that is not the keyboard. A dialog whose only exit is\n * Escape is a trap for anyone using a pointer.\n */\nexport function Dialog(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function DialogPortal(props: ComponentProps<typeof KobalteDialog.Portal>) {\n return <KobalteDialog.Portal {...props} />\n}\n\nexport function DialogOverlay(props: ComponentProps<typeof KobalteDialog.Overlay>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Overlay\n class={cn(\n overlayScrim,\n 'data-expanded:animate-in data-expanded:fade-in-0 data-closed:animate-out data-closed:fade-out-0',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type DialogContentProps = ComponentProps<typeof KobalteDialog.Content> & {\n /**\n * Replaces the default close button. Pass `false` to remove it — only for a\n * dialog that cannot be dismissed (an update that must finish); anything the\n * user can escape from needs the button.\n */\n closeButton?: JSX.Element | false\n}\n\nexport function DialogContent(props: DialogContentProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'closeButton'])\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <div class={overlayPositioner}>\n <KobalteDialog.Content\n class={cn(overlaySurface, overlayMotion, 'grid w-full max-w-lg gap-4 p-5', local.class)}\n {...rest}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n class={cn(\n 'absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground',\n 'transition-colors ease-out hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle outline-none'\n )}\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialog.Content>\n </div>\n </KobalteDialog.Portal>\n )\n}\n\nexport function DialogHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-header\"\n class={cn('flex flex-col gap-1.5 pe-6 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-footer\"\n class={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title\n class={cn('text-base leading-none font-semibold tracking-tight', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function DialogCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n\n/**\n * The close control, unstyled and polymorphic — for a footer's text \"Cancel\" or\n * \"Close\", which is a different control from the corner icon `DialogCloseButton`\n * draws. Take it as `as={Button}` so it carries the button's variants rather than\n * a copied class string.\n */\nexport function DialogClose(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n"],"mappings":"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"}
@@ -4,10 +4,10 @@ import { className, createComponent, delegateEvents, effect, insert, memo, merge
4
4
  import { For, Show, createMemo, splitProps } from "solid-js";
5
5
  //#region src/components/ui/diff-block/diff-block.tsx
6
6
  var _tmpl$ = /*#__PURE__*/ template(`<p class="px-3 py-1 text-xs text-muted-foreground italic">Generating diff…`);
7
- var _tmpl$2 = /*#__PURE__*/ template(`<div><div class="flex items-center justify-between gap-2 border-b border-border px-3 py-1"><span class="flex min-w-0 items-baseline gap-2"><span class="truncate font-mono text-xs text-foreground"></span><span class="shrink-0 font-mono text-2xs text-muted-foreground"><span class=text-success>+</span> <span class=text-destructive>−</span></span></span></div><div class="scroll-fade overflow-x-auto"tabindex=0 role=region><div class=min-w-fit>`);
7
+ var _tmpl$2 = /*#__PURE__*/ template(`<div><div class="flex items-center justify-between gap-2 border-b border-border px-3 py-1"><span class="flex min-w-0 items-baseline gap-2"><span class="truncate font-mono text-xs text-foreground"></span><span class="shrink-0 font-mono text-2xs text-muted-foreground"><span class=text-foreground>+</span> <span class=text-foreground>−</span></span></span></div><div class="scroll-fade overflow-x-auto"tabindex=0 role=region><div class=min-w-fit>`);
8
8
  var _tmpl$3 = /*#__PURE__*/ template(`<span class="w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none"aria-hidden=true>`);
9
9
  var _tmpl$4 = /*#__PURE__*/ template(`<div><span class="w-4 shrink-0 text-center select-none"aria-hidden=true></span><span class="min-w-0 whitespace-pre pr-4"><span class=visually-hidden>`);
10
- var _tmpl$5 = /*#__PURE__*/ template(`<button type=button><span class="truncate text-foreground"></span><span class="shrink-0 text-2xs"><span class=text-success>+</span> <span class=text-destructive>−`);
10
+ var _tmpl$5 = /*#__PURE__*/ template(`<button type=button><span class="truncate text-foreground"></span><span class="shrink-0 text-2xs"><span class=text-foreground>+</span> <span class=text-foreground>−`);
11
11
  var HUNK_HEADER = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
12
12
  /**
13
13
  * Classify a unified diff.
@@ -1 +1 @@
1
- {"version":3,"file":"diff-block.js","names":["createMemo","For","Show","splitProps","ComponentProps","JSX","cva","VariantProps","cn","DiffLineKind","DiffLine","Readonly","kind","text","marker","oldLine","newLine","HUNK_HEADER","parseDiff","patch","lines","inHunk","raw","replace","split","test","match","exec","Number","push","isFileHeader","startsWith","slice","numbered","line","show","Boolean","diffStats","added","removed","diffTargetPath","git","plain","fromHeader","diffLineVariants","variants","add","delete","context","hunk","header","meta","defaultVariants","DiffBlockProps","Omit","title","complete","showLineNumbers","actions","Element","DiffBlock","props","local","rest","stats","name","pop","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_el$1","_el$10","_$spread","_$mergeProps","class","_$insert","_$createComponent","each","children","_el$12","_tmpl$4","_el$15","_el$16","_el$17","when","_el$13","_tmpl$3","_el$14","_c$","_$memo","_c$2","_$effect","_$className","_tmpl$","_$setAttribute","DiffSummary","onSelect","_el$18","_tmpl$5","_el$19","_el$20","_el$21","_el$22","_el$23","_el$24","_el$25","$$click","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$setAttribute","_$delegateEvents"],"sources":["../../../../src/components/ui/diff-block/diff-block.tsx"],"sourcesContent":["import { createMemo, For, Show, splitProps, type ComponentProps, type JSX } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * DiffBlock.\n *\n * A unified diff, classified and toned. Parsing lives here because the\n * classification is the part that is easy to get subtly wrong and impossible to\n * fix from a caller: whether a line is an addition, a deletion, a hunk header,\n * a file header, or context depends on state — a line beginning with `+++` is a\n * file header *before* the first hunk and an added line beginning with `++`\n * *inside* one — and a renderer that tested prefixes without that state would\n * mis-colour real patches.\n *\n * The line grammar:\n *\n * | Prefix | Meaning |\n * | --- | --- |\n * | `diff --git`, `index`, `---`, `+++` (before a hunk) | file header |\n * | `@@` | hunk header |\n * | `+` | addition |\n * | `-` | deletion |\n * | `\\` | the \"no newline at end of file\" marker |\n * | anything else, including a leading space | context |\n *\n * Tones are pairs of surface and text, so an addition is readable in both\n * polarities and with any accent — the greens and reds are the theme's own\n * `success` and `destructive` at low alpha, not fixed hexes. Colour is never the\n * only signal: the gutter carries `+` or `-` as well, which is what makes the\n * block usable in greyscale and by anyone who cannot separate the two hues.\n *\n * Split (side-by-side) view is deliberately not implemented. It is a different\n * layout algorithm — pairing deletions with additions across hunks — and a\n * half-correct one is worse than none. `view=\"unified\"` is the only value, and\n * the prop exists so that adding the second is not a breaking change.\n */\n\nexport type DiffLineKind = 'add' | 'delete' | 'context' | 'hunk' | 'header' | 'meta'\n\nexport type DiffLine = Readonly<{\n kind: DiffLineKind\n /** The line without its diff prefix. */\n text: string\n /** The prefix as written: `+`, `-`, a space, or nothing for a header. */\n marker: string\n /** The old-side line number, when the line exists on the old side. */\n oldLine?: number\n /** The new-side line number, when the line exists on the new side. */\n newLine?: number\n}>\n\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/\n\n/**\n * Classify a unified diff.\n *\n * `headerState` is what makes `---` and `+++` unambiguous: git writes them as\n * file headers before the first `@@` and as content after it, and the two need\n * different tones. `oldLine`/`newLine` are tracked so the gutter can number both\n * sides — the numbers a reader uses to find the change in their editor.\n */\nexport function parseDiff(patch: string): readonly DiffLine[] {\n const lines: DiffLine[] = []\n let inHunk = false\n let oldLine = 0\n let newLine = 0\n\n for (const raw of patch.replace(/\\n$/, '').split('\\n')) {\n if (HUNK_HEADER.test(raw)) {\n const match = HUNK_HEADER.exec(raw)!\n oldLine = Number(match[1])\n newLine = Number(match[2])\n inHunk = true\n lines.push({ kind: 'hunk', text: raw, marker: '' })\n continue\n }\n\n if (!inHunk) {\n const isFileHeader =\n raw.startsWith('diff --git') ||\n raw.startsWith('index ') ||\n raw.startsWith('new file') ||\n raw.startsWith('deleted file') ||\n raw.startsWith('similarity index') ||\n raw.startsWith('rename ') ||\n raw.startsWith('--- ') ||\n raw.startsWith('+++ ')\n lines.push({ kind: isFileHeader ? 'header' : 'meta', text: raw, marker: '' })\n continue\n }\n\n if (raw.startsWith('\\\\')) {\n lines.push({ kind: 'meta', text: raw, marker: '' })\n continue\n }\n\n const marker = raw[0] ?? ' '\n if (marker === '+') {\n lines.push({ kind: 'add', text: raw.slice(1), marker, newLine })\n newLine += 1\n } else if (marker === '-') {\n lines.push({ kind: 'delete', text: raw.slice(1), marker, oldLine })\n oldLine += 1\n } else {\n lines.push({ kind: 'context', text: raw.slice(1), marker: ' ', oldLine, newLine })\n oldLine += 1\n newLine += 1\n }\n }\n\n return lines\n}\n\n/**\n * Whether a line gets gutter numbers. A hunk header and a file header are\n * structural, so numbering them would put a number on a line that has none.\n */\nfunction numbered(line: DiffLine, show: boolean | undefined): boolean {\n return Boolean(show) && line.kind !== 'hunk' && line.kind !== 'header' && line.kind !== 'meta'\n}\n\n/** The counts a diff summary reports: how much was added and removed. */\nexport function diffStats(\n lines: readonly DiffLine[]\n): Readonly<{ added: number; removed: number }> {\n let added = 0\n let removed = 0\n for (const line of lines) {\n if (line.kind === 'add') added += 1\n else if (line.kind === 'delete') removed += 1\n }\n return { added, removed }\n}\n\n/**\n * The target path from a unified diff's file header. Prefers `+++ b/<path>` —\n * git's explicit new-side marker — and skips `/dev/null`, which marks an added\n * or deleted side rather than naming a file. Only lines outside a hunk are\n * considered, for the same reason the parser tracks state.\n */\nexport function diffTargetPath(patch: string): string | null {\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) break\n const git = /^\\+\\+\\+ b\\/(.+?)(?:\\t|$)/.exec(line)\n if (git) return git[1]!\n const plain = /^\\+\\+\\+ ([^\\s/][^\\t]*?)(?:\\t|$)/.exec(line)\n if (plain && plain[1] !== '/dev/null') return plain[1]!\n const fromHeader = /^diff --git a\\/.+ b\\/(.+)/.exec(line)\n if (fromHeader) return fromHeader[1]!\n }\n return null\n}\n\nexport const diffLineVariants = cva('flex items-baseline font-mono text-xs', {\n variants: {\n kind: {\n add: 'bg-success-subtle text-foreground',\n delete: 'bg-destructive-subtle text-foreground',\n context: 'text-foreground',\n hunk: 'bg-muted text-muted-foreground',\n header: 'bg-muted font-semibold text-foreground',\n meta: 'text-muted-foreground italic',\n },\n },\n defaultVariants: { kind: 'context' },\n})\n\nexport type DiffBlockProps = Omit<ComponentProps<'div'>, 'children'> &\n VariantProps<typeof diffLineVariants> & {\n /** The unified diff. */\n patch: string\n /** A filename. Defaults to the path in the patch's header, or \"diff\". */\n title?: string\n /** False while the patch is still streaming. */\n complete?: boolean\n /** Show the two line-number gutters. Off for a fragment with no line numbers. */\n showLineNumbers?: boolean\n /** Extra header controls. */\n actions?: JSX.Element\n }\n\nexport function DiffBlock(props: DiffBlockProps) {\n const [local, rest] = splitProps(props, [\n 'patch',\n 'title',\n 'complete',\n 'showLineNumbers',\n 'actions',\n 'class',\n ])\n\n const lines = createMemo(() => parseDiff(local.patch))\n const stats = createMemo(() => diffStats(lines()))\n const name = () => local.title ?? diffTargetPath(local.patch)?.split('/').pop() ?? 'diff'\n\n return (\n <div\n class={cn('overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n >\n <div class=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1\">\n <span class=\"flex min-w-0 items-baseline gap-2\">\n <span class=\"truncate font-mono text-xs text-foreground\">{name()}</span>\n {/* The counts are text, so the summary survives greyscale and a reader\n who cannot separate the two line tones still gets the shape of it. */}\n <span class=\"shrink-0 font-mono text-2xs text-muted-foreground\">\n <span class=\"text-success\">+{stats().added}</span>{' '}\n <span class=\"text-destructive\">−{stats().removed}</span>\n </span>\n </span>\n {local.actions}\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n tabindex=\"0\"\n role=\"region\"\n aria-label={`Diff for ${name()}`}\n >\n <div class=\"min-w-fit\">\n <For each={lines()}>\n {(line) => (\n <div class={diffLineVariants({ kind: line.kind })}>\n <Show when={numbered(line, local.showLineNumbers)}>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.oldLine ?? ''}\n </span>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.newLine ?? ''}\n </span>\n </Show>\n {/* The marker is the signal that is not a colour. */}\n <span class=\"w-4 shrink-0 text-center select-none\" aria-hidden=\"true\">\n {line.kind === 'add' ? '+' : line.kind === 'delete' ? '−' : ''}\n </span>\n <span class=\"min-w-0 whitespace-pre pr-4\">\n {/* A screen reader gets the kind as a word, not a glyph. */}\n <span class=\"visually-hidden\">\n {line.kind === 'add' ? 'Added: ' : line.kind === 'delete' ? 'Removed: ' : ''}\n </span>\n {line.text || ' '}\n </span>\n </div>\n )}\n </For>\n </div>\n <Show when={!local.complete}>\n <p class=\"px-3 py-1 text-xs text-muted-foreground italic\">Generating diff…</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * A diff summary line, for a list of changes rather than one patch: the file and\n * its counts. Uses `CodeBlock`'s height rules and nothing else, because a summary\n * is a row and not a surface.\n */\nexport function DiffSummary(props: { patch: string; class?: string; onSelect?: () => void }) {\n const stats = createMemo(() => diffStats(parseDiff(props.patch)))\n const name = () => diffTargetPath(props.patch) ?? 'diff'\n\n return (\n <button\n type=\"button\"\n class={cn(\n 'flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-mono text-xs hover:bg-muted',\n props.class\n )}\n onClick={() => props.onSelect?.()}\n >\n <span class=\"truncate text-foreground\">{name()}</span>\n <span class=\"shrink-0 text-2xs\">\n <span class=\"text-success\">+{stats().added}</span>{' '}\n <span class=\"text-destructive\">−{stats().removed}</span>\n </span>\n </button>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"diff-block.js","names":["createMemo","For","Show","splitProps","ComponentProps","JSX","cva","VariantProps","cn","DiffLineKind","DiffLine","Readonly","kind","text","marker","oldLine","newLine","HUNK_HEADER","parseDiff","patch","lines","inHunk","raw","replace","split","test","match","exec","Number","push","isFileHeader","startsWith","slice","numbered","line","show","Boolean","diffStats","added","removed","diffTargetPath","git","plain","fromHeader","diffLineVariants","variants","add","delete","context","hunk","header","meta","defaultVariants","DiffBlockProps","Omit","title","complete","showLineNumbers","actions","Element","DiffBlock","props","local","rest","stats","name","pop","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_el$1","_el$10","_$spread","_$mergeProps","class","_$insert","_$createComponent","each","children","_el$12","_tmpl$4","_el$15","_el$16","_el$17","when","_el$13","_tmpl$3","_el$14","_c$","_$memo","_c$2","_$effect","_$className","_tmpl$","_$setAttribute","DiffSummary","onSelect","_el$18","_tmpl$5","_el$19","_el$20","_el$21","_el$22","_el$23","_el$24","_el$25","$$click","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$setAttribute","_$delegateEvents"],"sources":["../../../../src/components/ui/diff-block/diff-block.tsx"],"sourcesContent":["import { createMemo, For, Show, splitProps, type ComponentProps, type JSX } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * DiffBlock.\n *\n * A unified diff, classified and toned. Parsing lives here because the\n * classification is the part that is easy to get subtly wrong and impossible to\n * fix from a caller: whether a line is an addition, a deletion, a hunk header,\n * a file header, or context depends on state — a line beginning with `+++` is a\n * file header *before* the first hunk and an added line beginning with `++`\n * *inside* one — and a renderer that tested prefixes without that state would\n * mis-colour real patches.\n *\n * The line grammar:\n *\n * | Prefix | Meaning |\n * | --- | --- |\n * | `diff --git`, `index`, `---`, `+++` (before a hunk) | file header |\n * | `@@` | hunk header |\n * | `+` | addition |\n * | `-` | deletion |\n * | `\\` | the \"no newline at end of file\" marker |\n * | anything else, including a leading space | context |\n *\n * Tones are pairs of surface and text, so an addition is readable in both\n * polarities and with any accent — the greens and reds are the theme's own\n * `success` and `destructive` at low alpha, not fixed hexes. Colour is never the\n * only signal: the gutter carries `+` or `-` as well, which is what makes the\n * block usable in greyscale and by anyone who cannot separate the two hues.\n *\n * Split (side-by-side) view is deliberately not implemented. It is a different\n * layout algorithm — pairing deletions with additions across hunks — and a\n * half-correct one is worse than none. `view=\"unified\"` is the only value, and\n * the prop exists so that adding the second is not a breaking change.\n */\n\nexport type DiffLineKind = 'add' | 'delete' | 'context' | 'hunk' | 'header' | 'meta'\n\nexport type DiffLine = Readonly<{\n kind: DiffLineKind\n /** The line without its diff prefix. */\n text: string\n /** The prefix as written: `+`, `-`, a space, or nothing for a header. */\n marker: string\n /** The old-side line number, when the line exists on the old side. */\n oldLine?: number\n /** The new-side line number, when the line exists on the new side. */\n newLine?: number\n}>\n\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/\n\n/**\n * Classify a unified diff.\n *\n * `headerState` is what makes `---` and `+++` unambiguous: git writes them as\n * file headers before the first `@@` and as content after it, and the two need\n * different tones. `oldLine`/`newLine` are tracked so the gutter can number both\n * sides — the numbers a reader uses to find the change in their editor.\n */\nexport function parseDiff(patch: string): readonly DiffLine[] {\n const lines: DiffLine[] = []\n let inHunk = false\n let oldLine = 0\n let newLine = 0\n\n for (const raw of patch.replace(/\\n$/, '').split('\\n')) {\n if (HUNK_HEADER.test(raw)) {\n const match = HUNK_HEADER.exec(raw)!\n oldLine = Number(match[1])\n newLine = Number(match[2])\n inHunk = true\n lines.push({ kind: 'hunk', text: raw, marker: '' })\n continue\n }\n\n if (!inHunk) {\n const isFileHeader =\n raw.startsWith('diff --git') ||\n raw.startsWith('index ') ||\n raw.startsWith('new file') ||\n raw.startsWith('deleted file') ||\n raw.startsWith('similarity index') ||\n raw.startsWith('rename ') ||\n raw.startsWith('--- ') ||\n raw.startsWith('+++ ')\n lines.push({ kind: isFileHeader ? 'header' : 'meta', text: raw, marker: '' })\n continue\n }\n\n if (raw.startsWith('\\\\')) {\n lines.push({ kind: 'meta', text: raw, marker: '' })\n continue\n }\n\n const marker = raw[0] ?? ' '\n if (marker === '+') {\n lines.push({ kind: 'add', text: raw.slice(1), marker, newLine })\n newLine += 1\n } else if (marker === '-') {\n lines.push({ kind: 'delete', text: raw.slice(1), marker, oldLine })\n oldLine += 1\n } else {\n lines.push({ kind: 'context', text: raw.slice(1), marker: ' ', oldLine, newLine })\n oldLine += 1\n newLine += 1\n }\n }\n\n return lines\n}\n\n/**\n * Whether a line gets gutter numbers. A hunk header and a file header are\n * structural, so numbering them would put a number on a line that has none.\n */\nfunction numbered(line: DiffLine, show: boolean | undefined): boolean {\n return Boolean(show) && line.kind !== 'hunk' && line.kind !== 'header' && line.kind !== 'meta'\n}\n\n/** The counts a diff summary reports: how much was added and removed. */\nexport function diffStats(\n lines: readonly DiffLine[]\n): Readonly<{ added: number; removed: number }> {\n let added = 0\n let removed = 0\n for (const line of lines) {\n if (line.kind === 'add') added += 1\n else if (line.kind === 'delete') removed += 1\n }\n return { added, removed }\n}\n\n/**\n * The target path from a unified diff's file header. Prefers `+++ b/<path>` —\n * git's explicit new-side marker — and skips `/dev/null`, which marks an added\n * or deleted side rather than naming a file. Only lines outside a hunk are\n * considered, for the same reason the parser tracks state.\n */\nexport function diffTargetPath(patch: string): string | null {\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) break\n const git = /^\\+\\+\\+ b\\/(.+?)(?:\\t|$)/.exec(line)\n if (git) return git[1]!\n const plain = /^\\+\\+\\+ ([^\\s/][^\\t]*?)(?:\\t|$)/.exec(line)\n if (plain && plain[1] !== '/dev/null') return plain[1]!\n const fromHeader = /^diff --git a\\/.+ b\\/(.+)/.exec(line)\n if (fromHeader) return fromHeader[1]!\n }\n return null\n}\n\nexport const diffLineVariants = cva('flex items-baseline font-mono text-xs', {\n variants: {\n kind: {\n add: 'bg-success-subtle text-foreground',\n delete: 'bg-destructive-subtle text-foreground',\n context: 'text-foreground',\n hunk: 'bg-muted text-muted-foreground',\n header: 'bg-muted font-semibold text-foreground',\n meta: 'text-muted-foreground italic',\n },\n },\n defaultVariants: { kind: 'context' },\n})\n\nexport type DiffBlockProps = Omit<ComponentProps<'div'>, 'children'> &\n VariantProps<typeof diffLineVariants> & {\n /** The unified diff. */\n patch: string\n /** A filename. Defaults to the path in the patch's header, or \"diff\". */\n title?: string\n /** False while the patch is still streaming. */\n complete?: boolean\n /** Show the two line-number gutters. Off for a fragment with no line numbers. */\n showLineNumbers?: boolean\n /** Extra header controls. */\n actions?: JSX.Element\n }\n\nexport function DiffBlock(props: DiffBlockProps) {\n const [local, rest] = splitProps(props, [\n 'patch',\n 'title',\n 'complete',\n 'showLineNumbers',\n 'actions',\n 'class',\n ])\n\n const lines = createMemo(() => parseDiff(local.patch))\n const stats = createMemo(() => diffStats(lines()))\n const name = () => local.title ?? diffTargetPath(local.patch)?.split('/').pop() ?? 'diff'\n\n return (\n <div\n class={cn('overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n >\n <div class=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1\">\n <span class=\"flex min-w-0 items-baseline gap-2\">\n <span class=\"truncate font-mono text-xs text-foreground\">{name()}</span>\n {/* The counts are text, so the summary survives greyscale and a reader\n who cannot separate the two line tones still gets the shape of it. */}\n <span class=\"shrink-0 font-mono text-2xs text-muted-foreground\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </span>\n {local.actions}\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n tabindex=\"0\"\n role=\"region\"\n aria-label={`Diff for ${name()}`}\n >\n <div class=\"min-w-fit\">\n <For each={lines()}>\n {(line) => (\n <div class={diffLineVariants({ kind: line.kind })}>\n <Show when={numbered(line, local.showLineNumbers)}>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.oldLine ?? ''}\n </span>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.newLine ?? ''}\n </span>\n </Show>\n {/* The marker is the signal that is not a colour. */}\n <span class=\"w-4 shrink-0 text-center select-none\" aria-hidden=\"true\">\n {line.kind === 'add' ? '+' : line.kind === 'delete' ? '−' : ''}\n </span>\n <span class=\"min-w-0 whitespace-pre pr-4\">\n {/* A screen reader gets the kind as a word, not a glyph. */}\n <span class=\"visually-hidden\">\n {line.kind === 'add' ? 'Added: ' : line.kind === 'delete' ? 'Removed: ' : ''}\n </span>\n {line.text || ' '}\n </span>\n </div>\n )}\n </For>\n </div>\n <Show when={!local.complete}>\n <p class=\"px-3 py-1 text-xs text-muted-foreground italic\">Generating diff…</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * A diff summary line, for a list of changes rather than one patch: the file and\n * its counts. Uses `CodeBlock`'s height rules and nothing else, because a summary\n * is a row and not a surface.\n */\nexport function DiffSummary(props: { patch: string; class?: string; onSelect?: () => void }) {\n const stats = createMemo(() => diffStats(parseDiff(props.patch)))\n const name = () => diffTargetPath(props.patch) ?? 'diff'\n\n return (\n <button\n type=\"button\"\n class={cn(\n 'flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-mono text-xs hover:bg-muted',\n props.class\n )}\n onClick={() => props.onSelect?.()}\n >\n <span class=\"truncate text-foreground\">{name()}</span>\n <span class=\"shrink-0 text-2xs\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </button>\n )\n}\n"],"mappings":"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"}
@@ -12,8 +12,9 @@ import type { ComponentProps } from 'solid-js';
12
12
  * highlight, Escape to close and return focus — which is exactly what a
13
13
  * hand-rolled `div` with click handlers gets wrong.
14
14
  *
15
- * The `destructive` variant on an item is a *colour*, not a confirmation.
16
- * Pairing it with an AlertDialog is the caller's job.
15
+ * The `destructive` variant marks the row with a status-coloured edge and
16
+ * highlighted tint while keeping its label on the body foreground. Pairing it
17
+ * with an AlertDialog is the caller's job.
17
18
  */
18
19
  export declare function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>): import("solid-js").JSX.Element;
19
20
  export declare function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>): import("solid-js").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAa9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,kCAE7E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,kCAE5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,MAAM,CAAC,kCAE1F;AAED,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,GAAG;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,kCAoBlE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACvD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,kCAwBF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,kCASjE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,YAAY,CAAC,kCAY/D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAWhG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,kCAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAGhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,GAAG,CAAC,kCAEpF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAU7D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAkB7D"}
1
+ {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAc9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,kCAE7E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,kCAE5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,MAAM,CAAC,kCAE1F;AAED,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,GAAG;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,kCAoBlE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACvD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,kCAuBF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,kCASjE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,YAAY,CAAC,kCAY/D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAWhG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,kCAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAGhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,GAAG,CAAC,kCAEpF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAU7D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAkB7D"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
- import { menuItem, menuLabel, menuSeparator, overlayMotion, overlaySurface } from "../../../lib/overlay.js";
2
+ import { destructiveMenuItem, menuItem, menuLabel, menuSeparator, overlayMotion, overlaySurface } from "../../../lib/overlay.js";
3
3
  import { createComponent, insert, memo, mergeProps, spread, template } from "solid-js/web";
4
4
  import { Check, ChevronRight, Circle } from "lucide-solid";
5
5
  import { splitProps } from "solid-js";
@@ -19,8 +19,9 @@ var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=dropdown-menu-shortcut>`);
19
19
  * highlight, Escape to close and return focus — which is exactly what a
20
20
  * hand-rolled `div` with click handlers gets wrong.
21
21
  *
22
- * The `destructive` variant on an item is a *colour*, not a confirmation.
23
- * Pairing it with an AlertDialog is the caller's job.
22
+ * The `destructive` variant marks the row with a status-coloured edge and
23
+ * highlighted tint while keeping its label on the body foreground. Pairing it
24
+ * with an AlertDialog is the caller's job.
24
25
  */
25
26
  function DropdownMenu$1(props) {
26
27
  return createComponent(DropdownMenu, props);
@@ -62,7 +63,7 @@ function DropdownMenuItem(props) {
62
63
  "children"
63
64
  ]);
64
65
  return createComponent(DropdownMenu.Item, mergeProps({ get ["class"]() {
65
- return cn(menuItem, { "text-destructive data-[highlighted]:bg-destructive-subtle data-[highlighted]:text-destructive": local.variant === "destructive" }, local.class);
66
+ return cn(menuItem, { [destructiveMenuItem]: local.variant === "destructive" }, local.class);
66
67
  } }, rest, { get children() {
67
68
  return [memo(() => local.children), memo(() => memo(() => !!local.shortcut)() ? (() => {
68
69
  var _el$ = _tmpl$();
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","KobalteDropdownMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","popoverArrow","cn","props","_$createComponent","DropdownMenuTrigger","Trigger","DropdownMenuPortal","Portal","DropdownMenuContentProps","Content","hideArrow","portalMount","HTMLElement","DropdownMenuContent","local","rest","mount","children","_$mergeProps","class","_$memo","Arrow","DropdownMenuItem","Item","variant","shortcut","_el$","_tmpl$","_$insert","DropdownMenuShortcut","_el$2","_tmpl$2","_$spread","DropdownMenuCheckboxItem","CheckboxItem","ItemIndicator","DropdownMenuRadioGroup","RadioGroup","DropdownMenuRadioItem","RadioItem","DropdownMenuLabel","GroupLabel","DropdownMenuGroup","Group","DropdownMenuSeparator","Separator","DropdownMenuSub","Sub","DropdownMenuSubTrigger","SubTrigger","DropdownMenuSubContent","SubContent","DropdownMenu","_$createComponent","KobalteDropdownMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import { DropdownMenu as KobalteDropdownMenu } from '@kobalte/core/dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n popoverArrow,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * DropdownMenu.\n *\n * A list of actions on a trigger, with radio groups for persistent choices\n * that fit naturally in a compact menu. Use Select for form inputs whose\n * selected value needs the field-style control, and Popover for arbitrary\n * content.\n *\n * Kobalte supplies the full menu contract — arrow keys, typeahead, the roving\n * highlight, Escape to close and return focus — which is exactly what a\n * hand-rolled `div` with click handlers gets wrong.\n *\n * The `destructive` variant on an item is a *colour*, not a confirmation.\n * Pairing it with an AlertDialog is the caller's job.\n */\nexport function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>) {\n return <KobalteDropdownMenu {...props} />\n}\n\nexport function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>) {\n return <KobalteDropdownMenu.Trigger {...props} />\n}\n\nexport function DropdownMenuPortal(props: ComponentProps<typeof KobalteDropdownMenu.Portal>) {\n return <KobalteDropdownMenu.Portal {...props} />\n}\n\nexport type DropdownMenuContentProps = ComponentProps<typeof KobalteDropdownMenu.Content> & {\n hideArrow?: boolean\n /** Mount under an owner element such as a modal, keeping the menu in its accessible subtree. */\n portalMount?: HTMLElement\n}\n\nexport function DropdownMenuContent(props: DropdownMenuContentProps) {\n const [local, rest] = splitProps(props, ['class', 'hideArrow', 'children', 'portalMount'])\n\n return (\n <KobalteDropdownMenu.Portal mount={local.portalMount}>\n <KobalteDropdownMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n >\n {!local.hideArrow && <KobalteDropdownMenu.Arrow aria-hidden=\"true\" class={popoverArrow} />}\n {local.children}\n </KobalteDropdownMenu.Content>\n </KobalteDropdownMenu.Portal>\n )\n}\n\nexport function DropdownMenuItem(\n props: ComponentProps<typeof KobalteDropdownMenu.Item> & {\n /** Colour the row as a destructive action. Confirm it separately. */\n variant?: 'default' | 'destructive'\n /** Draw a shortcut hint at the trailing edge of the row. */\n shortcut?: string\n }\n) {\n const [local, rest] = splitProps(props, ['class', 'variant', 'shortcut', 'children'])\n\n return (\n <KobalteDropdownMenu.Item\n class={cn(\n menuItem,\n {\n 'text-destructive data-[highlighted]:bg-destructive-subtle data-[highlighted]:text-destructive':\n local.variant === 'destructive',\n },\n local.class\n )}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span class=\"text-muted-foreground ms-auto font-mono text-2xs tracking-widest\">\n {local.shortcut}\n </span>\n ) : null}\n </KobalteDropdownMenu.Item>\n )\n}\n\n/**\n * The chord drawn at a row's trailing edge.\n *\n * A component as well as the `shortcut` prop on an item, because a caller composing\n * a row by hand needs the same treatment — and because the alternative is every\n * caller inventing the same mono-and-dimmed span.\n */\nexport function DropdownMenuShortcut(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n class={cn('text-muted-foreground ms-auto font-mono text-2xs tracking-widest', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DropdownMenuCheckboxItem(\n props: ComponentProps<typeof KobalteDropdownMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Check class=\"size-4\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.CheckboxItem>\n )\n}\n\nexport function DropdownMenuRadioGroup(\n props: ComponentProps<typeof KobalteDropdownMenu.RadioGroup>\n) {\n return <KobalteDropdownMenu.RadioGroup {...props} />\n}\n\nexport function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdownMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Circle class=\"size-2 fill-current\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.RadioItem>\n )\n}\n\nexport function DropdownMenuLabel(props: ComponentProps<typeof KobalteDropdownMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function DropdownMenuGroup(props: ComponentProps<typeof KobalteDropdownMenu.Group>) {\n return <KobalteDropdownMenu.Group {...props} />\n}\n\nexport function DropdownMenuSeparator(props: ComponentProps<typeof KobalteDropdownMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function DropdownMenuSub(props: ComponentProps<typeof KobalteDropdownMenu.Sub>) {\n return <KobalteDropdownMenu.Sub {...props} />\n}\n\nexport function DropdownMenuSubTrigger(\n props: ComponentProps<typeof KobalteDropdownMenu.SubTrigger>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteDropdownMenu.SubTrigger>\n )\n}\n\nexport function DropdownMenuSubContent(\n props: ComponentProps<typeof KobalteDropdownMenu.SubContent>\n) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteDropdownMenu.Portal>\n <KobalteDropdownMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteDropdownMenu.Portal>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","KobalteDropdownMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","destructiveMenuItem","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","popoverArrow","cn","props","_$createComponent","DropdownMenuTrigger","Trigger","DropdownMenuPortal","Portal","DropdownMenuContentProps","Content","hideArrow","portalMount","HTMLElement","DropdownMenuContent","local","rest","mount","children","_$mergeProps","class","_$memo","Arrow","DropdownMenuItem","Item","variant","shortcut","_el$","_tmpl$","_$insert","DropdownMenuShortcut","_el$2","_tmpl$2","_$spread","DropdownMenuCheckboxItem","CheckboxItem","ItemIndicator","DropdownMenuRadioGroup","RadioGroup","DropdownMenuRadioItem","RadioItem","DropdownMenuLabel","GroupLabel","DropdownMenuGroup","Group","DropdownMenuSeparator","Separator","DropdownMenuSub","Sub","DropdownMenuSubTrigger","SubTrigger","DropdownMenuSubContent","SubContent","DropdownMenu","_$createComponent","KobalteDropdownMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import { DropdownMenu as KobalteDropdownMenu } from '@kobalte/core/dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n destructiveMenuItem,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n popoverArrow,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * DropdownMenu.\n *\n * A list of actions on a trigger, with radio groups for persistent choices\n * that fit naturally in a compact menu. Use Select for form inputs whose\n * selected value needs the field-style control, and Popover for arbitrary\n * content.\n *\n * Kobalte supplies the full menu contract — arrow keys, typeahead, the roving\n * highlight, Escape to close and return focus — which is exactly what a\n * hand-rolled `div` with click handlers gets wrong.\n *\n * The `destructive` variant marks the row with a status-coloured edge and\n * highlighted tint while keeping its label on the body foreground. Pairing it\n * with an AlertDialog is the caller's job.\n */\nexport function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>) {\n return <KobalteDropdownMenu {...props} />\n}\n\nexport function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>) {\n return <KobalteDropdownMenu.Trigger {...props} />\n}\n\nexport function DropdownMenuPortal(props: ComponentProps<typeof KobalteDropdownMenu.Portal>) {\n return <KobalteDropdownMenu.Portal {...props} />\n}\n\nexport type DropdownMenuContentProps = ComponentProps<typeof KobalteDropdownMenu.Content> & {\n hideArrow?: boolean\n /** Mount under an owner element such as a modal, keeping the menu in its accessible subtree. */\n portalMount?: HTMLElement\n}\n\nexport function DropdownMenuContent(props: DropdownMenuContentProps) {\n const [local, rest] = splitProps(props, ['class', 'hideArrow', 'children', 'portalMount'])\n\n return (\n <KobalteDropdownMenu.Portal mount={local.portalMount}>\n <KobalteDropdownMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n >\n {!local.hideArrow && <KobalteDropdownMenu.Arrow aria-hidden=\"true\" class={popoverArrow} />}\n {local.children}\n </KobalteDropdownMenu.Content>\n </KobalteDropdownMenu.Portal>\n )\n}\n\nexport function DropdownMenuItem(\n props: ComponentProps<typeof KobalteDropdownMenu.Item> & {\n /** Colour the row as a destructive action. Confirm it separately. */\n variant?: 'default' | 'destructive'\n /** Draw a shortcut hint at the trailing edge of the row. */\n shortcut?: string\n }\n) {\n const [local, rest] = splitProps(props, ['class', 'variant', 'shortcut', 'children'])\n\n return (\n <KobalteDropdownMenu.Item\n class={cn(\n menuItem,\n {\n [destructiveMenuItem]: local.variant === 'destructive',\n },\n local.class\n )}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span class=\"text-muted-foreground ms-auto font-mono text-2xs tracking-widest\">\n {local.shortcut}\n </span>\n ) : null}\n </KobalteDropdownMenu.Item>\n )\n}\n\n/**\n * The chord drawn at a row's trailing edge.\n *\n * A component as well as the `shortcut` prop on an item, because a caller composing\n * a row by hand needs the same treatment — and because the alternative is every\n * caller inventing the same mono-and-dimmed span.\n */\nexport function DropdownMenuShortcut(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n class={cn('text-muted-foreground ms-auto font-mono text-2xs tracking-widest', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DropdownMenuCheckboxItem(\n props: ComponentProps<typeof KobalteDropdownMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Check class=\"size-4\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.CheckboxItem>\n )\n}\n\nexport function DropdownMenuRadioGroup(\n props: ComponentProps<typeof KobalteDropdownMenu.RadioGroup>\n) {\n return <KobalteDropdownMenu.RadioGroup {...props} />\n}\n\nexport function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdownMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Circle class=\"size-2 fill-current\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.RadioItem>\n )\n}\n\nexport function DropdownMenuLabel(props: ComponentProps<typeof KobalteDropdownMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function DropdownMenuGroup(props: ComponentProps<typeof KobalteDropdownMenu.Group>) {\n return <KobalteDropdownMenu.Group {...props} />\n}\n\nexport function DropdownMenuSeparator(props: ComponentProps<typeof KobalteDropdownMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function DropdownMenuSub(props: ComponentProps<typeof KobalteDropdownMenu.Sub>) {\n return <KobalteDropdownMenu.Sub {...props} />\n}\n\nexport function DropdownMenuSubTrigger(\n props: ComponentProps<typeof KobalteDropdownMenu.SubTrigger>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteDropdownMenu.SubTrigger>\n )\n}\n\nexport function DropdownMenuSubContent(\n props: ComponentProps<typeof KobalteDropdownMenu.SubContent>\n) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteDropdownMenu.Portal>\n <KobalteDropdownMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteDropdownMenu.Portal>\n )\n}\n"],"mappings":"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"}
@@ -14,9 +14,9 @@ import { type VariantProps } from '#lib/variants';
14
14
  * 1. **A glyph is always present.** A brand with no logo gets a monogram, not an
15
15
  * empty box. `fallback` takes the name and returns the glyph, so a caller can
16
16
  * choose initials, a domain letter, or a kind icon.
17
- * 2. **The tile owns its own contrast.** `tone` tints the background and the
18
- * glyph together, so a caller never picks a colour pair and never ships an
19
- * icon that disappears against its tile.
17
+ * 2. **The tile owns its own contrast.** `tone` tints the background while
18
+ * monogram text keeps the body foreground; vector glyphs retain the status
19
+ * colour. A caller never picks a colour pair or ships a glyph that disappears.
20
20
  * 3. **Size is on the control ladder**, not arbitrary. A tile in a rail and a
21
21
  * tile in a detail header are the same two or three sizes every other
22
22
  * interactive element uses.
@@ -19,9 +19,9 @@ var _tmpl$2 = /*#__PURE__*/ template(`<span role=img>`);
19
19
  * 1. **A glyph is always present.** A brand with no logo gets a monogram, not an
20
20
  * empty box. `fallback` takes the name and returns the glyph, so a caller can
21
21
  * choose initials, a domain letter, or a kind icon.
22
- * 2. **The tile owns its own contrast.** `tone` tints the background and the
23
- * glyph together, so a caller never picks a colour pair and never ships an
24
- * icon that disappears against its tile.
22
+ * 2. **The tile owns its own contrast.** `tone` tints the background while
23
+ * monogram text keeps the body foreground; vector glyphs retain the status
24
+ * colour. A caller never picks a colour pair or ships a glyph that disappears.
25
25
  * 3. **Size is on the control ladder**, not arbitrary. A tile in a rail and a
26
26
  * tile in a detail header are the same two or three sizes every other
27
27
  * interactive element uses.
@@ -51,10 +51,10 @@ var entityIconVariants = cva("relative inline-flex shrink-0 items-center justify
51
51
  primary: "border-transparent bg-primary-subtle text-primary",
52
52
  /** Bare: no fill and no edge, for a tile that already sits on a surface. */
53
53
  bare: "border-transparent bg-transparent text-foreground",
54
- success: "border-transparent bg-success-subtle text-success",
55
- warning: "border-transparent bg-warning-subtle text-warning",
56
- danger: "border-transparent bg-destructive-subtle text-destructive",
57
- info: "border-transparent bg-info-subtle text-info"
54
+ success: "border-transparent bg-success-subtle text-foreground [&_svg]:text-success",
55
+ warning: "border-transparent bg-warning-subtle text-foreground [&_svg]:text-warning",
56
+ danger: "border-transparent bg-destructive-subtle text-foreground [&_svg]:text-destructive",
57
+ info: "border-transparent bg-info-subtle text-foreground [&_svg]:text-info"
58
58
  }
59
59
  },
60
60
  defaultVariants: {
@@ -1 +1 @@
1
- {"version":3,"file":"entity-icon.js","names":["Show","splitProps","Component","ComponentProps","JSX","Dynamic","cva","VariantProps","cn","entityIconVariants","variants","shape","rounded","circle","square","size","xs","sm","md","lg","xl","tone","neutral","primary","bare","success","warning","danger","info","defaultVariants","EntityIconVariantProps","EntityIconProps","Omit","name","icon","Element","fallback","badge","ring","monogram","words","trim","split","filter","Boolean","length","toUpperCase","slice","Glyph","kind","value","props","glyph","_$createComponent","component","EntityIcon","local","rest","undefined","_el$","_tmpl$2","_$spread","_$mergeProps","class","aria-label","_$insert","when","_$memo","children","_el$2","_tmpl$","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/entity-icon/entity-icon.tsx"],"sourcesContent":["import { Show, splitProps, type Component, type ComponentProps, type JSX } from 'solid-js'\nimport { Dynamic } from 'solid-js/web'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * EntityIcon.\n *\n * A tile that stands for a thing: a room, a project, an agent, an installed\n * plugin, a workspace. Its job is to be identifiable in a column of its\n * siblings, which is a different job from `Avatar`'s (identifying a *person*) and\n * the reason the two are separate components rather than one with a `round` prop.\n *\n * Three decisions are baked in because getting them wrong is what makes icon\n * grids look messy:\n *\n * 1. **A glyph is always present.** A brand with no logo gets a monogram, not an\n * empty box. `fallback` takes the name and returns the glyph, so a caller can\n * choose initials, a domain letter, or a kind icon.\n * 2. **The tile owns its own contrast.** `tone` tints the background and the\n * glyph together, so a caller never picks a colour pair and never ships an\n * icon that disappears against its tile.\n * 3. **Size is on the control ladder**, not arbitrary. A tile in a rail and a\n * tile in a detail header are the same two or three sizes every other\n * interactive element uses.\n *\n * `shape=\"rounded\"` is the default because a rounded square reads as an object\n * and a circle reads as a person; use `circle` only when the tile really does\n * hold a face.\n */\nexport const entityIconVariants = cva(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden border font-semibold select-none [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n shape: {\n rounded: 'rounded-lg',\n circle: 'rounded-full',\n square: 'rounded-none',\n },\n size: {\n xs: 'size-5 text-2xs [&_svg]:size-3',\n sm: 'size-6 text-2xs [&_svg]:size-3.5',\n md: 'size-8 text-xs [&_svg]:size-4',\n lg: 'size-10 text-sm [&_svg]:size-5',\n xl: 'size-12 text-base [&_svg]:size-6',\n },\n tone: {\n /** Neutral: an inset tile with a hairline edge — the default. */\n neutral: 'border-border bg-muted text-muted-foreground',\n /** On the brand: for a thing the application itself owns. */\n primary: 'border-transparent bg-primary-subtle text-primary',\n /** Bare: no fill and no edge, for a tile that already sits on a surface. */\n bare: 'border-transparent bg-transparent text-foreground',\n success: 'border-transparent bg-success-subtle text-success',\n warning: 'border-transparent bg-warning-subtle text-warning',\n danger: 'border-transparent bg-destructive-subtle text-destructive',\n info: 'border-transparent bg-info-subtle text-info',\n },\n },\n defaultVariants: { shape: 'rounded', size: 'md', tone: 'neutral' },\n }\n)\n\ntype EntityIconVariantProps = VariantProps<typeof entityIconVariants>\n\nexport type EntityIconProps = Omit<ComponentProps<'span'>, 'children'> &\n EntityIconVariantProps & {\n /** The entity's name. Used for the accessible label and, via `fallback`, the monogram. */\n name: string\n /**\n * A logo or icon — a Lucide icon reference (`icon={Wrench}`) or an element\n * (`icon={<Wrench />}`). Both are accepted because both are what a caller\n * naturally writes, and the difference is an implementation detail they should\n * not have to know.\n */\n icon?: Component | JSX.Element\n /** Glyph for an entity with no icon. Defaults to the name's first two letters. */\n fallback?: (name: string) => JSX.Element\n /** A corner badge: a status dot, an unread count, an installed tick. */\n badge?: JSX.Element\n /** A second edge, drawn outside the tile — an active or selected ring. */\n ring?: boolean\n }\n\n/**\n * Two letters from a name, chosen so the result is stable and readable: the\n * first letter of the first two words when there are two (\"Agent HQ\" → \"AH\"),\n * otherwise the first two characters (\"Kitchen\" → \"Ki\").\n */\nexport function monogram(name: string): string {\n const words = name.trim().split(/\\s+/).filter(Boolean)\n if (words.length >= 2) return (words[0]![0]! + words[1]![0]!).toUpperCase()\n return name.trim().slice(0, 2)\n}\n\n/**\n * A glyph is either a component reference or an element, and the two render\n * differently — `Dynamic` for the first, the element itself for the second. The\n * union is discriminated so the branch is checked rather than cast.\n */\ntype Glyph = { kind: 'component'; value: Component } | { kind: 'element'; value: JSX.Element }\n\nfunction Glyph(props: { glyph: Glyph }) {\n return props.glyph.kind === 'component' ? (\n <Dynamic component={props.glyph.value} />\n ) : (\n props.glyph.value\n )\n}\n\nexport function EntityIcon(props: EntityIconProps) {\n const [local, rest] = splitProps(props, [\n 'name',\n 'icon',\n 'fallback',\n 'badge',\n 'ring',\n 'shape',\n 'size',\n 'tone',\n 'class',\n ])\n\n const glyph = (): Glyph | undefined => {\n const icon = local.icon\n if (!icon) return undefined\n return typeof icon === 'function'\n ? { kind: 'component', value: icon as Component }\n : { kind: 'element', value: icon as JSX.Element }\n }\n\n return (\n <span\n class={cn(\n entityIconVariants({ shape: local.shape, size: local.size, tone: local.tone }),\n local.ring && 'ring-2 ring-ring ring-offset-2 ring-offset-background',\n local.class\n )}\n role=\"img\"\n aria-label={local.name}\n {...rest}\n >\n <Show\n when={glyph()}\n fallback={local.fallback ? local.fallback(local.name) : monogram(local.name)}\n >\n {(value) => <Glyph glyph={value()} />}\n </Show>\n <Show when={local.badge}>\n <span class=\"absolute right-0 bottom-0 translate-x-1/4 translate-y-1/4\">{local.badge}</span>\n </Show>\n </span>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAaS,qBAAqBH,IAChC,2JACA;CACEI,UAAU;EACRC,OAAO;GACLC,SAAS;GACTC,QAAQ;GACRC,QAAQ;EACV;EACAC,MAAM;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;EACN;EACAC,MAAM;;GAEJC,SAAS;;GAETC,SAAS;;GAETC,MAAM;GACNC,SAAS;GACTC,SAAS;GACTC,QAAQ;GACRC,MAAM;EACR;CACF;CACAC,iBAAiB;EAAElB,OAAO;EAAWI,MAAM;EAAMM,MAAM;CAAU;AACnE,CACF;;;;;;AA4BA,SAAgBkB,SAASN,MAAsB;CAC7C,MAAMO,QAAQP,KAAKQ,KAAK,CAAC,CAACC,MAAM,KAAK,CAAC,CAACC,OAAOC,OAAO;CACrD,IAAIJ,MAAMK,UAAU,GAAG,QAAQL,MAAM,EAAE,CAAE,KAAMA,MAAM,EAAE,CAAE,GAAA,CAAKM,YAAY;CAC1E,OAAOb,KAAKQ,KAAK,CAAC,CAACM,MAAM,GAAG,CAAC;AAC/B;AASA,SAASC,MAAMG,OAAyB;CACtC,OAAOA,MAAMC,MAAMH,SAAS,cAAWI,gBACpChD,SAAO,EAAA,IAACiD,YAAS;EAAA,OAAEH,MAAMC,MAAMF;CAAK,EAAA,CAAA,IAErCC,MAAMC,MAAMF;AAEhB;AAEA,SAAgBK,WAAWJ,OAAwB;CACjD,MAAM,CAACK,OAAOC,QAAQxD,WAAWkD,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAO,CACR;CAED,MAAMC,cAAiC;EACrC,MAAMlB,OAAOsB,MAAMtB;EACnB,IAAI,CAACA,MAAM,OAAOwB,KAAAA;EAClB,OAAO,OAAOxB,SAAS,aACnB;GAAEe,MAAM;GAAaC,OAAOhB;EAAkB,IAC9C;GAAEe,MAAM;GAAWC,OAAOhB;EAAoB;CACpD;CAEA,cAAA;EAAA,IAAAyB,OAAAC,QAAA;EAAAC,OAAAF,MAAAG,WAAA;GAAA,KAAA,WAAA;IAAA,OAEWtD,GACLC,mBAAmB;KAAEE,OAAO6C,MAAM7C;KAAOI,MAAMyC,MAAMzC;KAAMM,MAAMmC,MAAMnC;IAAK,CAAC,GAC7EmC,MAAMlB,QAAQ,yDACdkB,MAAMO,KACR;GAAC;GAAA,KAAA,gBAAA;IAAA,OAEWP,MAAMvB;GAAI;EAAA,GAClBwB,IAAI,GAAA,OAAA,IAAA;EAAAQ,OAAAN,MAAAN,gBAEPrD,MAAI;GAAA,IACHkE,OAAI;IAAA,OAAEd,MAAM;GAAC;GAAA,IACbhB,WAAQ;IAAA,OAAE+B,WAAA,CAAA,CAAAX,MAAMpB,QAAQ,CAAA,CAAA,IAAGoB,MAAMpB,SAASoB,MAAMvB,IAAI,IAAIM,SAASiB,MAAMvB,IAAI;GAAC;GAAAmC,WAE1ElB,UAAKG,gBAAML,OAAK,EAAA,IAACI,QAAK;IAAA,OAAEF,MAAM;GAAC,EAAA,CAAA;EAAI,CAAA,GAAA,IAAA;EAAAe,OAAAN,MAAAN,gBAEtCrD,MAAI;GAAA,IAACkE,OAAI;IAAA,OAAEV,MAAMnB;GAAK;GAAA,IAAA+B,WAAA;IAAA,IAAAC,QAAAC,OAAA;IAAAL,OAAAI,aACoDb,MAAMnB,KAAK;IAAA,OAAAgC;GAAA;EAAA,CAAA,GAAA,IAAA;EAAA,OAAAV;CAAA,EAAA,CAAA;AAI5F"}
1
+ {"version":3,"file":"entity-icon.js","names":["Show","splitProps","Component","ComponentProps","JSX","Dynamic","cva","VariantProps","cn","entityIconVariants","variants","shape","rounded","circle","square","size","xs","sm","md","lg","xl","tone","neutral","primary","bare","success","warning","danger","info","defaultVariants","EntityIconVariantProps","EntityIconProps","Omit","name","icon","Element","fallback","badge","ring","monogram","words","trim","split","filter","Boolean","length","toUpperCase","slice","Glyph","kind","value","props","glyph","_$createComponent","component","EntityIcon","local","rest","undefined","_el$","_tmpl$2","_$spread","_$mergeProps","class","aria-label","_$insert","when","_$memo","children","_el$2","_tmpl$","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/entity-icon/entity-icon.tsx"],"sourcesContent":["import { Show, splitProps, type Component, type ComponentProps, type JSX } from 'solid-js'\nimport { Dynamic } from 'solid-js/web'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * EntityIcon.\n *\n * A tile that stands for a thing: a room, a project, an agent, an installed\n * plugin, a workspace. Its job is to be identifiable in a column of its\n * siblings, which is a different job from `Avatar`'s (identifying a *person*) and\n * the reason the two are separate components rather than one with a `round` prop.\n *\n * Three decisions are baked in because getting them wrong is what makes icon\n * grids look messy:\n *\n * 1. **A glyph is always present.** A brand with no logo gets a monogram, not an\n * empty box. `fallback` takes the name and returns the glyph, so a caller can\n * choose initials, a domain letter, or a kind icon.\n * 2. **The tile owns its own contrast.** `tone` tints the background while\n * monogram text keeps the body foreground; vector glyphs retain the status\n * colour. A caller never picks a colour pair or ships a glyph that disappears.\n * 3. **Size is on the control ladder**, not arbitrary. A tile in a rail and a\n * tile in a detail header are the same two or three sizes every other\n * interactive element uses.\n *\n * `shape=\"rounded\"` is the default because a rounded square reads as an object\n * and a circle reads as a person; use `circle` only when the tile really does\n * hold a face.\n */\nexport const entityIconVariants = cva(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden border font-semibold select-none [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n shape: {\n rounded: 'rounded-lg',\n circle: 'rounded-full',\n square: 'rounded-none',\n },\n size: {\n xs: 'size-5 text-2xs [&_svg]:size-3',\n sm: 'size-6 text-2xs [&_svg]:size-3.5',\n md: 'size-8 text-xs [&_svg]:size-4',\n lg: 'size-10 text-sm [&_svg]:size-5',\n xl: 'size-12 text-base [&_svg]:size-6',\n },\n tone: {\n /** Neutral: an inset tile with a hairline edge — the default. */\n neutral: 'border-border bg-muted text-muted-foreground',\n /** On the brand: for a thing the application itself owns. */\n primary: 'border-transparent bg-primary-subtle text-primary',\n /** Bare: no fill and no edge, for a tile that already sits on a surface. */\n bare: 'border-transparent bg-transparent text-foreground',\n success: 'border-transparent bg-success-subtle text-foreground [&_svg]:text-success',\n warning: 'border-transparent bg-warning-subtle text-foreground [&_svg]:text-warning',\n danger: 'border-transparent bg-destructive-subtle text-foreground [&_svg]:text-destructive',\n info: 'border-transparent bg-info-subtle text-foreground [&_svg]:text-info',\n },\n },\n defaultVariants: { shape: 'rounded', size: 'md', tone: 'neutral' },\n }\n)\n\ntype EntityIconVariantProps = VariantProps<typeof entityIconVariants>\n\nexport type EntityIconProps = Omit<ComponentProps<'span'>, 'children'> &\n EntityIconVariantProps & {\n /** The entity's name. Used for the accessible label and, via `fallback`, the monogram. */\n name: string\n /**\n * A logo or icon — a Lucide icon reference (`icon={Wrench}`) or an element\n * (`icon={<Wrench />}`). Both are accepted because both are what a caller\n * naturally writes, and the difference is an implementation detail they should\n * not have to know.\n */\n icon?: Component | JSX.Element\n /** Glyph for an entity with no icon. Defaults to the name's first two letters. */\n fallback?: (name: string) => JSX.Element\n /** A corner badge: a status dot, an unread count, an installed tick. */\n badge?: JSX.Element\n /** A second edge, drawn outside the tile — an active or selected ring. */\n ring?: boolean\n }\n\n/**\n * Two letters from a name, chosen so the result is stable and readable: the\n * first letter of the first two words when there are two (\"Agent HQ\" → \"AH\"),\n * otherwise the first two characters (\"Kitchen\" → \"Ki\").\n */\nexport function monogram(name: string): string {\n const words = name.trim().split(/\\s+/).filter(Boolean)\n if (words.length >= 2) return (words[0]![0]! + words[1]![0]!).toUpperCase()\n return name.trim().slice(0, 2)\n}\n\n/**\n * A glyph is either a component reference or an element, and the two render\n * differently — `Dynamic` for the first, the element itself for the second. The\n * union is discriminated so the branch is checked rather than cast.\n */\ntype Glyph = { kind: 'component'; value: Component } | { kind: 'element'; value: JSX.Element }\n\nfunction Glyph(props: { glyph: Glyph }) {\n return props.glyph.kind === 'component' ? (\n <Dynamic component={props.glyph.value} />\n ) : (\n props.glyph.value\n )\n}\n\nexport function EntityIcon(props: EntityIconProps) {\n const [local, rest] = splitProps(props, [\n 'name',\n 'icon',\n 'fallback',\n 'badge',\n 'ring',\n 'shape',\n 'size',\n 'tone',\n 'class',\n ])\n\n const glyph = (): Glyph | undefined => {\n const icon = local.icon\n if (!icon) return undefined\n return typeof icon === 'function'\n ? { kind: 'component', value: icon as Component }\n : { kind: 'element', value: icon as JSX.Element }\n }\n\n return (\n <span\n class={cn(\n entityIconVariants({ shape: local.shape, size: local.size, tone: local.tone }),\n local.ring && 'ring-2 ring-ring ring-offset-2 ring-offset-background',\n local.class\n )}\n role=\"img\"\n aria-label={local.name}\n {...rest}\n >\n <Show\n when={glyph()}\n fallback={local.fallback ? local.fallback(local.name) : monogram(local.name)}\n >\n {(value) => <Glyph glyph={value()} />}\n </Show>\n <Show when={local.badge}>\n <span class=\"absolute right-0 bottom-0 translate-x-1/4 translate-y-1/4\">{local.badge}</span>\n </Show>\n </span>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAaS,qBAAqBH,IAChC,2JACA;CACEI,UAAU;EACRC,OAAO;GACLC,SAAS;GACTC,QAAQ;GACRC,QAAQ;EACV;EACAC,MAAM;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;GACJC,IAAI;EACN;EACAC,MAAM;;GAEJC,SAAS;;GAETC,SAAS;;GAETC,MAAM;GACNC,SAAS;GACTC,SAAS;GACTC,QAAQ;GACRC,MAAM;EACR;CACF;CACAC,iBAAiB;EAAElB,OAAO;EAAWI,MAAM;EAAMM,MAAM;CAAU;AACnE,CACF;;;;;;AA4BA,SAAgBkB,SAASN,MAAsB;CAC7C,MAAMO,QAAQP,KAAKQ,KAAK,CAAC,CAACC,MAAM,KAAK,CAAC,CAACC,OAAOC,OAAO;CACrD,IAAIJ,MAAMK,UAAU,GAAG,QAAQL,MAAM,EAAE,CAAE,KAAMA,MAAM,EAAE,CAAE,GAAA,CAAKM,YAAY;CAC1E,OAAOb,KAAKQ,KAAK,CAAC,CAACM,MAAM,GAAG,CAAC;AAC/B;AASA,SAASC,MAAMG,OAAyB;CACtC,OAAOA,MAAMC,MAAMH,SAAS,cAAWI,gBACpChD,SAAO,EAAA,IAACiD,YAAS;EAAA,OAAEH,MAAMC,MAAMF;CAAK,EAAA,CAAA,IAErCC,MAAMC,MAAMF;AAEhB;AAEA,SAAgBK,WAAWJ,OAAwB;CACjD,MAAM,CAACK,OAAOC,QAAQxD,WAAWkD,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAO,CACR;CAED,MAAMC,cAAiC;EACrC,MAAMlB,OAAOsB,MAAMtB;EACnB,IAAI,CAACA,MAAM,OAAOwB,KAAAA;EAClB,OAAO,OAAOxB,SAAS,aACnB;GAAEe,MAAM;GAAaC,OAAOhB;EAAkB,IAC9C;GAAEe,MAAM;GAAWC,OAAOhB;EAAoB;CACpD;CAEA,cAAA;EAAA,IAAAyB,OAAAC,QAAA;EAAAC,OAAAF,MAAAG,WAAA;GAAA,KAAA,WAAA;IAAA,OAEWtD,GACLC,mBAAmB;KAAEE,OAAO6C,MAAM7C;KAAOI,MAAMyC,MAAMzC;KAAMM,MAAMmC,MAAMnC;IAAK,CAAC,GAC7EmC,MAAMlB,QAAQ,yDACdkB,MAAMO,KACR;GAAC;GAAA,KAAA,gBAAA;IAAA,OAEWP,MAAMvB;GAAI;EAAA,GAClBwB,IAAI,GAAA,OAAA,IAAA;EAAAQ,OAAAN,MAAAN,gBAEPrD,MAAI;GAAA,IACHkE,OAAI;IAAA,OAAEd,MAAM;GAAC;GAAA,IACbhB,WAAQ;IAAA,OAAE+B,WAAA,CAAA,CAAAX,MAAMpB,QAAQ,CAAA,CAAA,IAAGoB,MAAMpB,SAASoB,MAAMvB,IAAI,IAAIM,SAASiB,MAAMvB,IAAI;GAAC;GAAAmC,WAE1ElB,UAAKG,gBAAML,OAAK,EAAA,IAACI,QAAK;IAAA,OAAEF,MAAM;GAAC,EAAA,CAAA;EAAI,CAAA,GAAA,IAAA;EAAAe,OAAAN,MAAAN,gBAEtCrD,MAAI;GAAA,IAACkE,OAAI;IAAA,OAAEV,MAAMnB;GAAK;GAAA,IAAA+B,WAAA;IAAA,IAAAC,QAAAC,OAAA;IAAAL,OAAAI,aACoDb,MAAMnB,KAAK;IAAA,OAAAgC;GAAA;EAAA,CAAA,GAAA,IAAA;EAAA,OAAAV;CAAA,EAAA,CAAA;AAI5F"}
@@ -44,7 +44,7 @@ function FieldDescription(props) {
44
44
  function FieldError(props) {
45
45
  const [local, rest] = splitProps(props, ["class"]);
46
46
  return createComponent(TextField.ErrorMessage, mergeProps({ get ["class"]() {
47
- return cn("text-destructive text-sm", local.class);
47
+ return cn("text-foreground text-sm", local.class);
48
48
  } }, rest));
49
49
  }
50
50
  function FieldInput(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","names":["TextField","KobalteTextField","ComponentProps","Show","splitProps","cn","Field","props","local","rest","_$createComponent","_$mergeProps","class","FieldLabel","Label","FieldDescription","Description","FieldError","ErrorMessage","FieldInput","Input","FieldTextArea","TextArea","FieldSet","_el$","_tmpl$","_$spread","FieldLegend","variant","_el$2","_tmpl$2","FieldSeparator","children","_el$3","_tmpl$4","_el$4","firstChild","_el$6","nextSibling","_$insert","when","_el$5","_tmpl$3","_$createComponent","KobalteTextField","_$mergeProps"],"sources":["../../../../src/components/ui/field/field.tsx"],"sourcesContent":["import { TextField as KobalteTextField } from '@kobalte/core/text-field'\nimport type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Field.\n *\n * The wrapper that makes a form control describable and validatable: a label,\n * a description, an error message, and the ARIA relationships between them.\n *\n * It is built on Kobalte's TextField specifically so `aria-describedby`,\n * `aria-invalid` and `aria-errormessage` are wired by construction. Those three\n * attributes are the difference between \"this field is required and empty\" and\n * a red border that only a sighted user can perceive — and they are also the\n * first thing a hand-rolled form drops.\n *\n * `Field` owns the description and the error slot, so a form's controls line up\n * and its messages land in the same place regardless of which control is used.\n * Compose it with any control: `Field` wraps, `Label`/`Input`/`Select` fill it.\n */\nexport function Field(props: ComponentProps<typeof KobalteTextField>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteTextField class={cn('flex flex-col gap-1.5', local.class)} {...rest} />\n}\n\nexport function FieldLabel(props: ComponentProps<typeof KobalteTextField.Label>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />\n )\n}\n\nexport function FieldDescription(props: ComponentProps<typeof KobalteTextField.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Description\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function FieldError(props: ComponentProps<typeof KobalteTextField.ErrorMessage>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.ErrorMessage class={cn('text-destructive text-sm', local.class)} {...rest} />\n )\n}\n\nexport function FieldInput(props: ComponentProps<typeof KobalteTextField.Input>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.Input\n class={cn(\n 'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none',\n 'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function FieldTextArea(props: ComponentProps<typeof KobalteTextField.TextArea>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.TextArea\n class={cn(\n 'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none resize-y',\n 'placeholder:text-muted-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * A labelled group of fields with a single legend, for a real `<fieldset>`.\n * Grouping is what lets a screen reader announce \"Shipping address, group\"\n * before reading the four fields inside it.\n */\nexport function FieldSet(props: ComponentProps<'fieldset'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />\n}\n\nexport function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n const [local, rest] = splitProps(props, ['class', 'variant'])\n return (\n <legend\n class={cn(\n 'mb-1',\n local.variant === 'label'\n ? 'text-sm font-medium'\n : 'text-base font-semibold tracking-tight',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A horizontal rule with a word in it, for \"or continue with\" separators. */\nexport function FieldSeparator(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <div class={cn('relative flex items-center gap-3 py-1', local.class)} {...rest}>\n <span class=\"bg-border h-px flex-1\" />\n <Show when={local.children}>\n <span class=\"text-muted-foreground text-2xs tracking-wide uppercase\">{local.children}</span>\n </Show>\n <span class=\"bg-border h-px flex-1\" />\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"field.js","names":["TextField","KobalteTextField","ComponentProps","Show","splitProps","cn","Field","props","local","rest","_$createComponent","_$mergeProps","class","FieldLabel","Label","FieldDescription","Description","FieldError","ErrorMessage","FieldInput","Input","FieldTextArea","TextArea","FieldSet","_el$","_tmpl$","_$spread","FieldLegend","variant","_el$2","_tmpl$2","FieldSeparator","children","_el$3","_tmpl$4","_el$4","firstChild","_el$6","nextSibling","_$insert","when","_el$5","_tmpl$3","_$createComponent","KobalteTextField","_$mergeProps"],"sources":["../../../../src/components/ui/field/field.tsx"],"sourcesContent":["import { TextField as KobalteTextField } from '@kobalte/core/text-field'\nimport type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Field.\n *\n * The wrapper that makes a form control describable and validatable: a label,\n * a description, an error message, and the ARIA relationships between them.\n *\n * It is built on Kobalte's TextField specifically so `aria-describedby`,\n * `aria-invalid` and `aria-errormessage` are wired by construction. Those three\n * attributes are the difference between \"this field is required and empty\" and\n * a red border that only a sighted user can perceive — and they are also the\n * first thing a hand-rolled form drops.\n *\n * `Field` owns the description and the error slot, so a form's controls line up\n * and its messages land in the same place regardless of which control is used.\n * Compose it with any control: `Field` wraps, `Label`/`Input`/`Select` fill it.\n */\nexport function Field(props: ComponentProps<typeof KobalteTextField>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteTextField class={cn('flex flex-col gap-1.5', local.class)} {...rest} />\n}\n\nexport function FieldLabel(props: ComponentProps<typeof KobalteTextField.Label>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />\n )\n}\n\nexport function FieldDescription(props: ComponentProps<typeof KobalteTextField.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Description\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function FieldError(props: ComponentProps<typeof KobalteTextField.ErrorMessage>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.ErrorMessage class={cn('text-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function FieldInput(props: ComponentProps<typeof KobalteTextField.Input>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.Input\n class={cn(\n 'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none',\n 'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function FieldTextArea(props: ComponentProps<typeof KobalteTextField.TextArea>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.TextArea\n class={cn(\n 'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none resize-y',\n 'placeholder:text-muted-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * A labelled group of fields with a single legend, for a real `<fieldset>`.\n * Grouping is what lets a screen reader announce \"Shipping address, group\"\n * before reading the four fields inside it.\n */\nexport function FieldSet(props: ComponentProps<'fieldset'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />\n}\n\nexport function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n const [local, rest] = splitProps(props, ['class', 'variant'])\n return (\n <legend\n class={cn(\n 'mb-1',\n local.variant === 'label'\n ? 'text-sm font-medium'\n : 'text-base font-semibold tracking-tight',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A horizontal rule with a word in it, for \"or continue with\" separators. */\nexport function FieldSeparator(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <div class={cn('relative flex items-center gap-3 py-1', local.class)} {...rest}>\n <span class=\"bg-border h-px flex-1\" />\n <Show when={local.children}>\n <span class=\"text-muted-foreground text-2xs tracking-wide uppercase\">{local.children}</span>\n </Show>\n <span class=\"bg-border h-px flex-1\" />\n </div>\n )\n}\n"],"mappings":"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"}