@deepfuture/dui-components 0.0.21 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +56 -65
  2. package/_install.js +11 -0
  3. package/accordion/accordion-item.d.ts +3 -20
  4. package/accordion/accordion-item.js +92 -292
  5. package/accordion/accordion.d.ts +3 -18
  6. package/accordion/accordion.js +9 -247
  7. package/accordion/index.d.ts +6 -6
  8. package/accordion/index.js +5 -5
  9. package/alert-dialog/alert-dialog-close.d.ts +3 -14
  10. package/alert-dialog/alert-dialog-close.js +4 -34
  11. package/alert-dialog/alert-dialog-popup.d.ts +3 -32
  12. package/alert-dialog/alert-dialog-popup.js +68 -317
  13. package/alert-dialog/alert-dialog-trigger.d.ts +3 -14
  14. package/alert-dialog/alert-dialog-trigger.js +4 -51
  15. package/alert-dialog/alert-dialog.d.ts +3 -30
  16. package/alert-dialog/alert-dialog.js +8 -158
  17. package/alert-dialog/index.d.ts +11 -11
  18. package/alert-dialog/index.js +9 -9
  19. package/all.d.ts +159 -123
  20. package/all.js +134 -231
  21. package/avatar/avatar.d.ts +3 -39
  22. package/avatar/avatar.js +18 -238
  23. package/avatar/index.d.ts +4 -4
  24. package/avatar/index.js +3 -3
  25. package/badge/badge.d.ts +3 -10
  26. package/badge/badge.js +87 -22
  27. package/badge/index.d.ts +2 -3
  28. package/badge/index.js +2 -3
  29. package/breadcrumb/breadcrumb-ellipsis.d.ts +3 -12
  30. package/breadcrumb/breadcrumb-ellipsis.js +8 -34
  31. package/breadcrumb/breadcrumb-item.d.ts +3 -11
  32. package/breadcrumb/breadcrumb-item.js +7 -26
  33. package/breadcrumb/breadcrumb-link.d.ts +3 -12
  34. package/breadcrumb/breadcrumb-link.js +16 -26
  35. package/breadcrumb/breadcrumb-page.d.ts +3 -11
  36. package/breadcrumb/breadcrumb-page.js +8 -31
  37. package/breadcrumb/breadcrumb-separator.d.ts +3 -12
  38. package/breadcrumb/breadcrumb-separator.js +8 -31
  39. package/breadcrumb/breadcrumb.d.ts +3 -12
  40. package/breadcrumb/breadcrumb.js +10 -33
  41. package/breadcrumb/index.d.ts +12 -13
  42. package/breadcrumb/index.js +12 -13
  43. package/button/button.d.ts +3 -32
  44. package/button/button.js +220 -165
  45. package/button/index.d.ts +3 -3
  46. package/button/index.js +3 -3
  47. package/calendar/calendar.d.ts +3 -31
  48. package/calendar/calendar.js +71 -481
  49. package/calendar/index.d.ts +3 -3
  50. package/calendar/index.js +3 -3
  51. package/card/card.d.ts +3 -27
  52. package/card/card.js +80 -163
  53. package/card/index.d.ts +2 -3
  54. package/card/index.js +2 -3
  55. package/card-grid/card-grid.d.ts +3 -15
  56. package/card-grid/card-grid.js +8 -106
  57. package/card-grid/index.d.ts +2 -3
  58. package/card-grid/index.js +2 -3
  59. package/checkbox/checkbox-group.d.ts +3 -34
  60. package/checkbox/checkbox-group.js +11 -188
  61. package/checkbox/checkbox.d.ts +3 -47
  62. package/checkbox/checkbox.js +43 -341
  63. package/checkbox/index.d.ts +6 -6
  64. package/checkbox/index.js +5 -5
  65. package/collapsible/collapsible.d.ts +3 -20
  66. package/collapsible/collapsible.js +82 -277
  67. package/collapsible/index.d.ts +3 -3
  68. package/collapsible/index.js +3 -3
  69. package/combobox/combobox.d.ts +3 -47
  70. package/combobox/combobox.js +136 -538
  71. package/combobox/index.d.ts +4 -4
  72. package/combobox/index.js +3 -3
  73. package/command/command-empty.d.ts +3 -8
  74. package/command/command-empty.js +10 -88
  75. package/command/command-group.d.ts +3 -13
  76. package/command/command-group.js +14 -114
  77. package/command/command-input.d.ts +3 -11
  78. package/command/command-input.js +20 -136
  79. package/command/command-item.d.ts +3 -18
  80. package/command/command-item.js +23 -212
  81. package/command/command-list.d.ts +3 -7
  82. package/command/command-list.js +11 -79
  83. package/command/command-separator.d.ts +3 -5
  84. package/command/command-separator.js +10 -11
  85. package/command/command-shortcut.d.ts +3 -5
  86. package/command/command-shortcut.js +9 -12
  87. package/command/command.d.ts +3 -23
  88. package/command/command.js +10 -339
  89. package/command/index.d.ts +17 -19
  90. package/command/index.js +16 -18
  91. package/data-table/data-table.d.ts +3 -57
  92. package/data-table/data-table.js +85 -449
  93. package/data-table/index.d.ts +3 -4
  94. package/data-table/index.js +2 -3
  95. package/dialog/dialog-close.d.ts +3 -14
  96. package/dialog/dialog-close.js +4 -34
  97. package/dialog/dialog-popup.d.ts +3 -34
  98. package/dialog/dialog-popup.js +70 -336
  99. package/dialog/dialog-trigger.d.ts +3 -14
  100. package/dialog/dialog-trigger.js +4 -51
  101. package/dialog/dialog.d.ts +3 -30
  102. package/dialog/dialog.js +8 -158
  103. package/dialog/index.d.ts +11 -11
  104. package/dialog/index.js +9 -9
  105. package/dropzone/dropzone.d.ts +3 -72
  106. package/dropzone/dropzone.js +29 -407
  107. package/dropzone/index.d.ts +4 -4
  108. package/dropzone/index.js +3 -3
  109. package/field/field.d.ts +3 -30
  110. package/field/field.js +34 -353
  111. package/field/index.d.ts +1 -0
  112. package/field/index.js +1 -0
  113. package/fieldset/fieldset.d.ts +3 -18
  114. package/fieldset/fieldset.js +21 -110
  115. package/fieldset/index.d.ts +1 -0
  116. package/fieldset/index.js +1 -0
  117. package/icon/icon.d.ts +3 -15
  118. package/icon/icon.js +4 -33
  119. package/icon/index.d.ts +2 -3
  120. package/icon/index.js +2 -3
  121. package/input/index.d.ts +3 -3
  122. package/input/index.js +3 -3
  123. package/input/input.d.ts +3 -49
  124. package/input/input.js +57 -238
  125. package/menu/index.d.ts +4 -5
  126. package/menu/index.js +4 -5
  127. package/menu/menu-item.d.ts +3 -13
  128. package/menu/menu-item.js +40 -91
  129. package/menu/menu.d.ts +3 -15
  130. package/menu/menu.js +27 -277
  131. package/menubar/index.d.ts +3 -4
  132. package/menubar/index.js +2 -3
  133. package/menubar/menubar.d.ts +3 -19
  134. package/menubar/menubar.js +12 -183
  135. package/number-field/index.d.ts +3 -3
  136. package/number-field/index.js +3 -3
  137. package/number-field/number-field.d.ts +3 -55
  138. package/number-field/number-field.js +205 -698
  139. package/package.json +125 -113
  140. package/popover/index.d.ts +11 -11
  141. package/popover/index.js +9 -9
  142. package/popover/popover-close.d.ts +3 -12
  143. package/popover/popover-close.js +4 -32
  144. package/popover/popover-popup.d.ts +3 -18
  145. package/popover/popover-popup.js +28 -205
  146. package/popover/popover-trigger.d.ts +3 -13
  147. package/popover/popover-trigger.js +4 -73
  148. package/popover/popover.d.ts +3 -29
  149. package/popover/popover.js +8 -207
  150. package/portal/index.d.ts +3 -4
  151. package/portal/index.js +2 -3
  152. package/portal/portal.d.ts +3 -27
  153. package/portal/portal.js +8 -157
  154. package/preview-card/index.d.ts +9 -9
  155. package/preview-card/index.js +7 -7
  156. package/preview-card/preview-card-popup.d.ts +3 -14
  157. package/preview-card/preview-card-popup.js +29 -194
  158. package/preview-card/preview-card-trigger.d.ts +3 -12
  159. package/preview-card/preview-card-trigger.js +4 -74
  160. package/preview-card/preview-card.d.ts +3 -33
  161. package/preview-card/preview-card.js +8 -239
  162. package/progress/index.d.ts +2 -3
  163. package/progress/index.js +2 -3
  164. package/progress/progress.d.ts +3 -17
  165. package/progress/progress.js +28 -130
  166. package/radio/index.d.ts +6 -6
  167. package/radio/index.js +5 -5
  168. package/radio/radio-group.d.ts +3 -37
  169. package/radio/radio-group.js +8 -200
  170. package/radio/radio.d.ts +3 -28
  171. package/radio/radio.js +38 -213
  172. package/scroll-area/index.d.ts +2 -3
  173. package/scroll-area/index.js +2 -3
  174. package/scroll-area/scroll-area.d.ts +3 -36
  175. package/scroll-area/scroll-area.js +25 -535
  176. package/select/index.d.ts +3 -4
  177. package/select/index.js +2 -3
  178. package/select/select.d.ts +3 -39
  179. package/select/select.js +115 -425
  180. package/separator/index.d.ts +2 -3
  181. package/separator/index.js +2 -3
  182. package/separator/separator.d.ts +3 -10
  183. package/separator/separator.js +23 -85
  184. package/sidebar/index.d.ts +29 -29
  185. package/sidebar/index.js +27 -32
  186. package/sidebar/sidebar-content.d.ts +3 -12
  187. package/sidebar/sidebar-content.js +7 -29
  188. package/sidebar/sidebar-footer.d.ts +3 -10
  189. package/sidebar/sidebar-footer.js +7 -20
  190. package/sidebar/sidebar-group-label.d.ts +3 -15
  191. package/sidebar/sidebar-group-label.js +16 -41
  192. package/sidebar/sidebar-group.d.ts +3 -13
  193. package/sidebar/sidebar-group.js +7 -24
  194. package/sidebar/sidebar-header.d.ts +3 -10
  195. package/sidebar/sidebar-header.js +7 -16
  196. package/sidebar/sidebar-inset.d.ts +3 -13
  197. package/sidebar/sidebar-inset.js +7 -28
  198. package/sidebar/sidebar-menu-button.d.ts +3 -26
  199. package/sidebar/sidebar-menu-button.js +59 -217
  200. package/sidebar/sidebar-menu-item.d.ts +3 -10
  201. package/sidebar/sidebar-menu-item.js +7 -19
  202. package/sidebar/sidebar-menu.d.ts +3 -12
  203. package/sidebar/sidebar-menu.js +7 -25
  204. package/sidebar/sidebar-provider.d.ts +3 -34
  205. package/sidebar/sidebar-provider.js +22 -232
  206. package/sidebar/sidebar-separator.d.ts +3 -10
  207. package/sidebar/sidebar-separator.js +9 -19
  208. package/sidebar/sidebar-trigger.d.ts +3 -14
  209. package/sidebar/sidebar-trigger.js +10 -46
  210. package/sidebar/sidebar.d.ts +3 -19
  211. package/sidebar/sidebar.js +65 -262
  212. package/slider/index.d.ts +3 -3
  213. package/slider/index.js +3 -3
  214. package/slider/slider.d.ts +3 -45
  215. package/slider/slider.js +97 -382
  216. package/spinner/index.d.ts +2 -3
  217. package/spinner/index.js +2 -3
  218. package/spinner/spinner.d.ts +3 -11
  219. package/spinner/spinner.js +20 -163
  220. package/split-button/index.d.ts +3 -1
  221. package/split-button/index.js +3 -1
  222. package/split-button/split-button.d.ts +3 -33
  223. package/split-button/split-button.js +306 -394
  224. package/stepper/index.d.ts +3 -3
  225. package/stepper/index.js +3 -3
  226. package/stepper/stepper.d.ts +3 -41
  227. package/stepper/stepper.js +57 -381
  228. package/switch/index.d.ts +3 -3
  229. package/switch/index.js +3 -3
  230. package/switch/switch.d.ts +3 -30
  231. package/switch/switch.js +63 -228
  232. package/tabs/index.d.ts +12 -12
  233. package/tabs/index.js +11 -11
  234. package/tabs/tab.d.ts +3 -14
  235. package/tabs/tab.js +32 -131
  236. package/tabs/tabs-indicator.d.ts +3 -9
  237. package/tabs/tabs-indicator.js +17 -22
  238. package/tabs/tabs-list.d.ts +3 -15
  239. package/tabs/tabs-list.js +14 -113
  240. package/tabs/tabs-panel.d.ts +3 -16
  241. package/tabs/tabs-panel.js +32 -114
  242. package/tabs/tabs.d.ts +3 -22
  243. package/tabs/tabs.js +8 -170
  244. package/textarea/index.d.ts +4 -4
  245. package/textarea/index.js +3 -3
  246. package/textarea/textarea.d.ts +3 -36
  247. package/textarea/textarea.js +63 -220
  248. package/toggle/index.d.ts +6 -6
  249. package/toggle/index.js +5 -5
  250. package/toggle/toggle-group.d.ts +3 -27
  251. package/toggle/toggle-group.js +9 -224
  252. package/toggle/toggle.d.ts +3 -26
  253. package/toggle/toggle.js +93 -178
  254. package/tokens/properties.css +361 -0
  255. package/tokens/prose.css +250 -0
  256. package/tokens/prose.d.ts +2 -0
  257. package/tokens/prose.js +4 -0
  258. package/tokens/tokens-raw.d.ts +2 -0
  259. package/tokens/tokens-raw.js +2 -0
  260. package/tokens/tokens.css +409 -0
  261. package/tokens/tokens.d.ts +2 -0
  262. package/tokens/tokens.js +5 -0
  263. package/toolbar/index.d.ts +2 -3
  264. package/toolbar/index.js +2 -3
  265. package/toolbar/toolbar.d.ts +3 -11
  266. package/toolbar/toolbar.js +25 -116
  267. package/tooltip/index.d.ts +9 -9
  268. package/tooltip/index.js +7 -7
  269. package/tooltip/tooltip-popup.d.ts +3 -14
  270. package/tooltip/tooltip-popup.js +31 -185
  271. package/tooltip/tooltip-trigger.d.ts +3 -14
  272. package/tooltip/tooltip-trigger.js +5 -148
  273. package/tooltip/tooltip.d.ts +3 -35
  274. package/tooltip/tooltip.js +8 -253
  275. package/trunc/index.d.ts +2 -3
  276. package/trunc/index.js +2 -3
  277. package/trunc/trunc.d.ts +3 -17
  278. package/trunc/trunc.js +10 -108
  279. package/_deprecated/center/center.d.ts +0 -14
  280. package/_deprecated/center/center.js +0 -37
  281. package/_deprecated/center/index.d.ts +0 -3
  282. package/_deprecated/center/index.js +0 -3
  283. package/_deprecated/center/register.js +0 -4
  284. package/_deprecated/hstack/hstack.d.ts +0 -25
  285. package/_deprecated/hstack/hstack.js +0 -187
  286. package/_deprecated/hstack/index.d.ts +0 -4
  287. package/_deprecated/hstack/index.js +0 -3
  288. package/_deprecated/hstack/register.d.ts +0 -1
  289. package/_deprecated/hstack/register.js +0 -4
  290. package/_deprecated/page-inset/index.d.ts +0 -3
  291. package/_deprecated/page-inset/index.js +0 -3
  292. package/_deprecated/page-inset/page-inset.d.ts +0 -28
  293. package/_deprecated/page-inset/page-inset.js +0 -151
  294. package/_deprecated/page-inset/register.d.ts +0 -1
  295. package/_deprecated/page-inset/register.js +0 -4
  296. package/_deprecated/vstack/index.d.ts +0 -3
  297. package/_deprecated/vstack/index.js +0 -3
  298. package/_deprecated/vstack/register.d.ts +0 -1
  299. package/_deprecated/vstack/register.js +0 -4
  300. package/_deprecated/vstack/vstack.d.ts +0 -17
  301. package/_deprecated/vstack/vstack.js +0 -125
  302. package/accordion/accordion-context.d.ts +0 -15
  303. package/accordion/accordion-context.js +0 -3
  304. package/alert-dialog/alert-dialog-context.d.ts +0 -13
  305. package/alert-dialog/alert-dialog-context.js +0 -3
  306. package/checkbox/checkbox-group-context.d.ts +0 -11
  307. package/checkbox/checkbox-group-context.js +0 -3
  308. package/command/command-context.d.ts +0 -30
  309. package/command/command-context.js +0 -3
  310. package/command/command-score.d.ts +0 -6
  311. package/command/command-score.js +0 -31
  312. package/dialog/dialog-context.d.ts +0 -13
  313. package/dialog/dialog-context.js +0 -3
  314. package/global.d.ts +0 -179
  315. package/menubar/menubar-context.d.ts +0 -9
  316. package/menubar/menubar-context.js +0 -2
  317. package/popover/popover-context.d.ts +0 -17
  318. package/popover/popover-context.js +0 -3
  319. package/preview-card/preview-card-context.d.ts +0 -16
  320. package/preview-card/preview-card-context.js +0 -3
  321. package/radio/radio-group-context.d.ts +0 -11
  322. package/radio/radio-group-context.js +0 -2
  323. package/sidebar/sidebar-context.d.ts +0 -15
  324. package/sidebar/sidebar-context.js +0 -3
  325. package/split-button/register.d.ts +0 -1
  326. package/split-button/register.js +0 -4
  327. package/tabs/tabs-context.d.ts +0 -8
  328. package/tabs/tabs-context.js +0 -2
  329. package/toggle/toggle-group-context.d.ts +0 -9
  330. package/toggle/toggle-group-context.js +0 -2
  331. package/tooltip/tooltip-context.d.ts +0 -17
  332. package/tooltip/tooltip-context.js +0 -3
  333. /package/{_deprecated/center/register.d.ts → _install.d.ts} +0 -0
@@ -1,566 +1,164 @@
1
- /** Ported from original DUI: deep-future-app/app/client/components/dui/combobox */
2
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
- var _, done = false;
8
- for (var i = decorators.length - 1; i >= 0; i--) {
9
- var context = {};
10
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
- if (kind === "accessor") {
15
- if (result === void 0) continue;
16
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
- if (_ = accept(result.get)) descriptor.get = _;
18
- if (_ = accept(result.set)) descriptor.set = _;
19
- if (_ = accept(result.init)) initializers.unshift(_);
20
- }
21
- else if (_ = accept(result)) {
22
- if (kind === "field") initializers.unshift(_);
23
- else descriptor[key] = _;
24
- }
25
- }
26
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
- done = true;
28
- };
29
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
- var useValue = arguments.length > 2;
31
- for (var i = 0; i < initializers.length; i++) {
32
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
- }
34
- return useValue ? value : void 0;
35
- };
36
- var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
37
- if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
38
- return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
39
- };
40
- import { css, html, LitElement, nothing } from "lit";
41
- import { property, state } from "lit/decorators.js";
42
- import { repeat } from "lit/directives/repeat.js";
43
- import { live } from "lit/directives/live.js";
44
- import { base } from "@deepfuture/dui-core/base";
45
- import { customEvent } from "@deepfuture/dui-core/event";
46
- import { FloatingPortalController } from "@deepfuture/dui-core/floating-portal-controller";
47
- export const valueChangeEvent = customEvent("value-change", { bubbles: true, composed: true });
48
- export const valuesChangeEvent = customEvent("values-change", { bubbles: true, composed: true });
49
- const hostStyles = css `
50
- :host {
51
- display: block;
52
- }
53
- `;
54
- const componentStyles = css `
55
- /* ---- Input area (structural) ---- */
1
+ import { css } from "lit";
2
+ import { DuiComboboxPrimitive } from "@deepfuture/dui-primitives/combobox";
3
+ import "../_install.js";
4
+ const styles = css `
5
+ /* ---- Chips (multi-select container) ---- */
56
6
 
57
7
  .Chips {
58
- position: relative;
59
- box-sizing: border-box;
60
- display: flex;
61
- flex-wrap: wrap;
62
- align-items: center;
63
- width: 100%;
64
- cursor: text;
8
+ gap: var(--space-1);
9
+ border: var(--border-width-thin) solid var(--border);
10
+ border-radius: var(--radius-md);
11
+ padding: var(--space-1) var(--space-8) var(--space-1) var(--space-1_5);
12
+ min-height: var(--component-height-md);
13
+ background: transparent;
14
+ transition-property: border-color, box-shadow;
15
+ transition-duration: var(--duration-fast);
65
16
  }
66
17
 
67
- .Chips[data-disabled] {
68
- cursor: not-allowed;
18
+ .Chips:focus-within:has(:focus-visible) {
19
+ box-shadow:
20
+ 0 0 0 var(--focus-ring-offset) var(--background),
21
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
69
22
  }
70
23
 
71
- .InputWrapper {
72
- position: relative;
73
- display: flex;
74
- align-items: center;
75
- width: 100%;
24
+ .Chips[data-disabled] {
25
+ opacity: 0.4;
76
26
  }
77
27
 
28
+ /* ---- Input ---- */
29
+
78
30
  .Input {
79
- box-sizing: border-box;
80
- border: none;
81
- outline: none;
31
+ height: var(--component-height-md);
32
+ color: var(--text-1);
33
+ font-family: var(--font-sans);
34
+ font-size: var(--text-sm); line-height: var(--text-sm--line-height);
35
+ }
36
+
37
+ :host([size="sm"]) .Input {
38
+ height: var(--component-height-sm);
39
+ font-size: var(--text-xs);
40
+ }
41
+
42
+ :host([size="sm"]) .Chips {
43
+ min-height: var(--component-height-sm);
44
+ }
45
+
46
+ :host([size="sm"]) .InputWrapper .Input {
47
+ min-height: var(--component-height-sm);
48
+ padding: var(--space-1_5) var(--space-8) var(--space-1_5) var(--space-1_5);
49
+ }
50
+
51
+ .Input::placeholder {
52
+ color: var(--text-3);
53
+ }
54
+
55
+ /* Single-select input wrapper */
56
+ .InputWrapper .Input {
57
+ width: 100%;
58
+ min-height: var(--component-height-md);
59
+ padding: var(--space-2) var(--space-8) var(--space-2) var(--space-2);
60
+ border: var(--border-width-thin) solid var(--border);
61
+ border-radius: var(--radius-md);
62
+ transition-property: border-color, box-shadow;
63
+ transition-duration: var(--duration-fast);
82
64
  background: transparent;
83
- padding: 0;
84
- min-width: 4rem;
85
- flex: 1;
86
65
  }
87
66
 
88
- .Input:disabled {
89
- cursor: not-allowed;
67
+ .InputWrapper .Input:focus-visible {
68
+ box-shadow:
69
+ 0 0 0 var(--focus-ring-offset) var(--background),
70
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
71
+ }
72
+
73
+ .InputWrapper .Input[data-disabled] {
74
+ opacity: 0.4;
90
75
  }
91
76
 
92
77
  .Arrow {
93
- position: absolute;
94
- pointer-events: none;
95
- flex-shrink: 0;
78
+ --icon-size: var(--space-4);
79
+ right: var(--space-3);
80
+ color: var(--text-1);
96
81
  }
97
82
 
98
- .Chip {
99
- display: inline-flex;
100
- align-items: center;
101
- cursor: default;
102
- max-width: 100%;
103
- overflow: hidden;
83
+ /* Multi-select input (inside chips) */
84
+ .Chips .Input {
85
+ height: var(--space-6);
86
+ margin-left: var(--space-1_5);
104
87
  }
105
88
 
106
- .ChipLabel {
107
- overflow: hidden;
108
- text-overflow: ellipsis;
109
- white-space: nowrap;
89
+ /* ---- Chip ---- */
90
+
91
+ .Chip {
92
+ gap: var(--space-1);
93
+ background: oklch(from var(--foreground) l c h / 0.05);
94
+ color: var(--text-1);
95
+ border-radius: var(--radius-sm);
96
+ font-size: var(--text-xs); line-height: var(--text-xs--line-height);
97
+ padding: var(--space-0_5) var(--space-0_5) var(--space-0_5) var(--space-2);
110
98
  }
111
99
 
112
100
  .ChipRemove {
113
- display: inline-flex;
114
- align-items: center;
115
- justify-content: center;
116
- border: none;
117
- background: none;
118
- cursor: pointer;
119
- flex-shrink: 0;
101
+ padding: var(--space-0_5);
102
+ color: inherit;
103
+ border-radius: var(--radius-sm);
104
+ --icon-size: var(--space-3_5);
120
105
  }
121
- `;
122
- /** Structural styles injected into the portal positioner. */
123
- const portalPopupStyles = [
124
- css `
125
- .Popup {
126
- opacity: 1;
127
- transform: translateY(0);
128
- transition-property: opacity, transform;
129
- pointer-events: auto;
130
- }
131
106
 
132
- .Popup[data-starting-style],
133
- .Popup[data-ending-style] {
134
- opacity: 0;
135
- }
107
+ .ChipRemove:hover {
108
+ background: color-mix(
109
+ in oklch,
110
+ var(--text-1) 15%,
111
+ transparent
112
+ );
113
+ }
136
114
 
137
- dui-scroll-area {
138
- max-height: 240px;
139
- height: auto;
140
- }
115
+ /* ---- Popup (rendered in portal shadow root) ---- */
141
116
 
142
- .Item {
143
- display: flex;
144
- align-items: center;
145
- cursor: pointer;
146
- }
117
+ .Popup {
118
+ background: var(--surface-3);
119
+ border: var(--border-width-thin) solid var(--border);
120
+ border-radius: var(--radius-md);
121
+ box-shadow: var(--shadow-md);
122
+ transition-duration: var(--duration-fast);
123
+ transition-timing-function: var(--ease-out-3);
124
+ }
147
125
 
148
- .ItemIndicator {
149
- flex-shrink: 0;
150
- display: flex;
151
- align-items: center;
152
- justify-content: center;
153
- }
126
+ .Popup[data-starting-style],
127
+ .Popup[data-ending-style] {
128
+ transform: translateY(calc(var(--space-1) * -1));
129
+ }
154
130
 
155
- .ItemText {
156
- flex: 1;
157
- overflow: hidden;
158
- text-overflow: ellipsis;
159
- white-space: nowrap;
160
- }
161
- `,
162
- ];
163
- /**
164
- * `<dui-combobox>` — A searchable dropdown for selecting from a list of options.
165
- * Supports single-select and multi-select (chip) modes.
166
- *
167
- * @fires value-change - Single-select: fired when selection changes.
168
- * Detail: { value: string, option: SelectOption }
169
- * @fires values-change - Multi-select: fired when a value is toggled.
170
- * Detail: { value: string, selected: boolean, values: Set<string> }
171
- */
172
- let DuiCombobox = (() => {
173
- let _classSuper = LitElement;
174
- let _options_decorators;
175
- let _options_initializers = [];
176
- let _options_extraInitializers = [];
177
- let _value_decorators;
178
- let _value_initializers = [];
179
- let _value_extraInitializers = [];
180
- let _values_decorators;
181
- let _values_initializers = [];
182
- let _values_extraInitializers = [];
183
- let _multiple_decorators;
184
- let _multiple_initializers = [];
185
- let _multiple_extraInitializers = [];
186
- let _placeholder_decorators;
187
- let _placeholder_initializers = [];
188
- let _placeholder_extraInitializers = [];
189
- let _disabled_decorators;
190
- let _disabled_initializers = [];
191
- let _disabled_extraInitializers = [];
192
- let _name_decorators;
193
- let _name_initializers = [];
194
- let _name_extraInitializers = [];
195
- let _private_highlightedIndex_decorators;
196
- let _private_highlightedIndex_initializers = [];
197
- let _private_highlightedIndex_extraInitializers = [];
198
- let _private_highlightedIndex_descriptor;
199
- let _private_inputValue_decorators;
200
- let _private_inputValue_initializers = [];
201
- let _private_inputValue_extraInitializers = [];
202
- let _private_inputValue_descriptor;
203
- return class DuiCombobox extends _classSuper {
204
- static {
205
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
206
- _options_decorators = [property({ attribute: false })];
207
- _value_decorators = [property({ type: String })];
208
- _values_decorators = [property({ attribute: false })];
209
- _multiple_decorators = [property({ type: Boolean, reflect: true })];
210
- _placeholder_decorators = [property({ type: String })];
211
- _disabled_decorators = [property({ type: Boolean, reflect: true })];
212
- _name_decorators = [property({ type: String })];
213
- _private_highlightedIndex_decorators = [state()];
214
- _private_inputValue_decorators = [state()];
215
- __esDecorate(this, null, _options_decorators, { kind: "accessor", name: "options", static: false, private: false, access: { has: obj => "options" in obj, get: obj => obj.options, set: (obj, value) => { obj.options = value; } }, metadata: _metadata }, _options_initializers, _options_extraInitializers);
216
- __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
217
- __esDecorate(this, null, _values_decorators, { kind: "accessor", name: "values", static: false, private: false, access: { has: obj => "values" in obj, get: obj => obj.values, set: (obj, value) => { obj.values = value; } }, metadata: _metadata }, _values_initializers, _values_extraInitializers);
218
- __esDecorate(this, null, _multiple_decorators, { kind: "accessor", name: "multiple", static: false, private: false, access: { has: obj => "multiple" in obj, get: obj => obj.multiple, set: (obj, value) => { obj.multiple = value; } }, metadata: _metadata }, _multiple_initializers, _multiple_extraInitializers);
219
- __esDecorate(this, null, _placeholder_decorators, { kind: "accessor", name: "placeholder", static: false, private: false, access: { has: obj => "placeholder" in obj, get: obj => obj.placeholder, set: (obj, value) => { obj.placeholder = value; } }, metadata: _metadata }, _placeholder_initializers, _placeholder_extraInitializers);
220
- __esDecorate(this, null, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
221
- __esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
222
- __esDecorate(this, _private_highlightedIndex_descriptor = { get: __setFunctionName(function () { return this.#highlightedIndex_accessor_storage; }, "#highlightedIndex", "get"), set: __setFunctionName(function (value) { this.#highlightedIndex_accessor_storage = value; }, "#highlightedIndex", "set") }, _private_highlightedIndex_decorators, { kind: "accessor", name: "#highlightedIndex", static: false, private: true, access: { has: obj => #highlightedIndex in obj, get: obj => obj.#highlightedIndex, set: (obj, value) => { obj.#highlightedIndex = value; } }, metadata: _metadata }, _private_highlightedIndex_initializers, _private_highlightedIndex_extraInitializers);
223
- __esDecorate(this, _private_inputValue_descriptor = { get: __setFunctionName(function () { return this.#inputValue_accessor_storage; }, "#inputValue", "get"), set: __setFunctionName(function (value) { this.#inputValue_accessor_storage = value; }, "#inputValue", "set") }, _private_inputValue_decorators, { kind: "accessor", name: "#inputValue", static: false, private: true, access: { has: obj => #inputValue in obj, get: obj => obj.#inputValue, set: (obj, value) => { obj.#inputValue = value; } }, metadata: _metadata }, _private_inputValue_initializers, _private_inputValue_extraInitializers);
224
- if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
225
- }
226
- static tagName = "dui-combobox";
227
- static formAssociated = true;
228
- static styles = [base, hostStyles, componentStyles];
229
- #internals;
230
- constructor() {
231
- super();
232
- this.#internals = this.attachInternals();
233
- }
234
- #options_accessor_storage = __runInitializers(this, _options_initializers, []);
235
- /** The available options. */
236
- get options() { return this.#options_accessor_storage; }
237
- set options(value) { this.#options_accessor_storage = value; }
238
- #value_accessor_storage = (__runInitializers(this, _options_extraInitializers), __runInitializers(this, _value_initializers, ""));
239
- /** Currently selected value (single-select mode). */
240
- get value() { return this.#value_accessor_storage; }
241
- set value(value) { this.#value_accessor_storage = value; }
242
- #values_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _values_initializers, new Set()));
243
- /** Currently selected values (multi-select mode). */
244
- get values() { return this.#values_accessor_storage; }
245
- set values(value) { this.#values_accessor_storage = value; }
246
- #multiple_accessor_storage = (__runInitializers(this, _values_extraInitializers), __runInitializers(this, _multiple_initializers, false));
247
- /** Enable multi-select mode with chips. */
248
- get multiple() { return this.#multiple_accessor_storage; }
249
- set multiple(value) { this.#multiple_accessor_storage = value; }
250
- #placeholder_accessor_storage = (__runInitializers(this, _multiple_extraInitializers), __runInitializers(this, _placeholder_initializers, "Search..."));
251
- /** Placeholder text for the input. */
252
- get placeholder() { return this.#placeholder_accessor_storage; }
253
- set placeholder(value) { this.#placeholder_accessor_storage = value; }
254
- #disabled_accessor_storage = (__runInitializers(this, _placeholder_extraInitializers), __runInitializers(this, _disabled_initializers, false));
255
- /** Whether the combobox is disabled. */
256
- get disabled() { return this.#disabled_accessor_storage; }
257
- set disabled(value) { this.#disabled_accessor_storage = value; }
258
- #name_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _name_initializers, ""));
259
- /** Name for form submission. */
260
- get name() { return this.#name_accessor_storage; }
261
- set name(value) { this.#name_accessor_storage = value; }
262
- willUpdate() {
263
- this.#syncFormValue();
264
- }
265
- #syncFormValue() {
266
- if (this.multiple) {
267
- const formData = new FormData();
268
- for (const v of this.values) {
269
- formData.append(this.name || "values", v);
270
- }
271
- this.#internals.setFormValue(formData);
272
- }
273
- else {
274
- this.#internals.setFormValue(this.value || null);
275
- }
276
- }
277
- #highlightedIndex_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _private_highlightedIndex_initializers, -1));
278
- get #highlightedIndex() { return _private_highlightedIndex_descriptor.get.call(this); }
279
- set #highlightedIndex(value) { return _private_highlightedIndex_descriptor.set.call(this, value); }
280
- #inputValue_accessor_storage = (__runInitializers(this, _private_highlightedIndex_extraInitializers), __runInitializers(this, _private_inputValue_initializers, ""));
281
- get #inputValue() { return _private_inputValue_descriptor.get.call(this); }
282
- set #inputValue(value) { return _private_inputValue_descriptor.set.call(this, value); }
283
- #popup = (__runInitializers(this, _private_inputValue_extraInitializers), new FloatingPortalController(this, {
284
- getAnchor: () => this.multiple
285
- ? this.shadowRoot?.querySelector(".Chips")
286
- : this.shadowRoot?.querySelector(".InputWrapper"),
287
- styles: portalPopupStyles,
288
- onOpen: () => {
289
- this.#highlightedIndex = -1;
290
- if (!this.multiple) {
291
- this.#inputValue = "";
292
- const input = this.shadowRoot?.querySelector(".Input");
293
- if (input)
294
- input.value = "";
295
- }
296
- },
297
- onClose: () => {
298
- this.#highlightedIndex = -1;
299
- if (!this.multiple) {
300
- const selected = this.options.find((o) => o.value === this.value);
301
- this.#inputValue = selected?.label ?? "";
302
- }
303
- },
304
- renderPopup: (portal) => {
305
- const filtered = this.#filteredOptions;
306
- const isEmpty = filtered.length === 0;
307
- return html `
308
- <div
309
- class="Popup"
310
- ?data-starting-style="${portal.isStarting}"
311
- ?data-ending-style="${portal.isEnding}"
312
- >
313
- <dui-scroll-area>
314
- <div
315
- class="List"
316
- id="${this.#listId}"
317
- role="listbox"
318
- aria-labelledby="${this.#inputId}"
319
- ?data-empty="${isEmpty}"
320
- @mousedown="${this.#onListMouseDown}"
321
- @mousemove="${this.#onListMouseMove}"
322
- >
323
- ${repeat(filtered, (option) => option.value, this.#renderItem)}
324
- ${isEmpty ? html ` <div class="Empty">No results</div> ` : nothing}
325
- </div>
326
- </dui-scroll-area>
327
- </div>
328
- `;
329
- },
330
- }));
331
- #inputId = `combobox-input-${crypto.randomUUID().slice(0, 8)}`;
332
- #listId = `combobox-list-${crypto.randomUUID().slice(0, 8)}`;
333
- /** Filtered options based on current input text. */
334
- get #filteredOptions() {
335
- const query = this.#inputValue.toLowerCase();
336
- const opts = this.options;
337
- if (!query)
338
- return opts;
339
- return opts.filter((opt) => opt.label.toLowerCase().includes(query));
340
- }
341
- // ---- Input handling ----
342
- #onInput = (event) => {
343
- const target = event.target;
344
- this.#inputValue = target.value;
345
- if (!this.#popup.isOpen) {
346
- if (!this.disabled)
347
- this.#popup.open();
348
- }
349
- this.#highlightedIndex = -1;
350
- };
351
- #onInputFocus = () => {
352
- if (!this.#popup.isOpen && !this.disabled) {
353
- this.#popup.open();
354
- }
355
- };
356
- #onInputKeyDown = (event) => {
357
- const filtered = this.#filteredOptions;
358
- switch (event.key) {
359
- case "ArrowDown":
360
- event.preventDefault();
361
- if (!this.#popup.isOpen) {
362
- if (!this.disabled)
363
- this.#popup.open();
364
- }
365
- else {
366
- this.#highlightedIndex = Math.min(this.#highlightedIndex + 1, filtered.length - 1);
367
- }
368
- break;
369
- case "ArrowUp":
370
- event.preventDefault();
371
- if (!this.#popup.isOpen) {
372
- if (!this.disabled)
373
- this.#popup.open();
374
- }
375
- else {
376
- this.#highlightedIndex = Math.max(this.#highlightedIndex - 1, 0);
377
- }
378
- break;
379
- case "Enter": {
380
- event.preventDefault();
381
- if (this.#popup.isOpen) {
382
- const index = this.#highlightedIndex >= 0 ? this.#highlightedIndex : 0;
383
- const option = filtered[index];
384
- if (option) {
385
- this.#selectOption(option);
386
- }
387
- }
388
- else if (!this.disabled) {
389
- this.#popup.open();
390
- }
391
- break;
392
- }
393
- case "Escape":
394
- if (this.#popup.isOpen) {
395
- event.preventDefault();
396
- this.#inputValue = "";
397
- this.#popup.close();
398
- }
399
- break;
400
- case "Tab":
401
- if (this.#popup.isOpen) {
402
- this.#popup.close();
403
- }
404
- break;
405
- case "Home":
406
- if (this.#popup.isOpen) {
407
- event.preventDefault();
408
- this.#highlightedIndex = 0;
409
- }
410
- break;
411
- case "End":
412
- if (this.#popup.isOpen) {
413
- event.preventDefault();
414
- this.#highlightedIndex = filtered.length - 1;
415
- }
416
- break;
417
- case "Backspace":
418
- if (this.multiple && this.#inputValue === "" && this.values.size > 0) {
419
- const lastValue = Array.from(this.values).at(-1);
420
- if (lastValue) {
421
- this.#removeValue(lastValue);
422
- }
423
- }
424
- break;
425
- }
426
- };
427
- // ---- Selection ----
428
- #selectOption(option) {
429
- if (this.multiple) {
430
- const newValues = new Set(this.values);
431
- const selected = !newValues.has(option.value);
432
- if (selected) {
433
- newValues.add(option.value);
434
- }
435
- else {
436
- newValues.delete(option.value);
437
- }
438
- this.values = newValues;
439
- this.#inputValue = "";
440
- this.#highlightedIndex = -1;
441
- this.dispatchEvent(valuesChangeEvent({
442
- value: option.value,
443
- selected,
444
- values: newValues,
445
- }));
446
- const input = this.shadowRoot?.querySelector(".Input");
447
- input?.focus();
448
- }
449
- else {
450
- this.value = option.value;
451
- this.#inputValue = option.label;
452
- this.dispatchEvent(valueChangeEvent({ value: option.value, option }));
453
- this.#popup.close();
454
- }
455
- }
456
- #removeValue(value) {
457
- const newValues = new Set(this.values);
458
- newValues.delete(value);
459
- this.values = newValues;
460
- this.dispatchEvent(valuesChangeEvent({ value, selected: false, values: newValues }));
461
- }
462
- #onItemClick = (option) => {
463
- this.#selectOption(option);
464
- };
465
- #onListMouseDown = (event) => {
466
- event.preventDefault();
467
- };
468
- #onListMouseMove = () => {
469
- if (this.#highlightedIndex !== -1) {
470
- this.#highlightedIndex = -1;
471
- }
472
- };
473
- #onChipsClick = () => {
474
- const input = this.shadowRoot?.querySelector(".Input");
475
- input?.focus();
476
- };
477
- // ---- Render ----
478
- #renderChip = (value) => {
479
- const option = this.options.find((o) => o.value === value);
480
- const label = option?.label ?? value;
481
- return html `
482
- <span class="Chip">
483
- <span class="ChipLabel">${label}</span>
484
- <button
485
- class="ChipRemove"
486
- type="button"
487
- tabindex="-1"
488
- @mousedown="${(e) => e.preventDefault()}"
489
- @click="${(e) => {
490
- e.stopPropagation();
491
- this.#removeValue(value);
492
- }}"
493
- >
494
- <dui-icon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></dui-icon>
495
- </button>
496
- </span>
497
- `;
498
- };
499
- #renderItem = (option, index) => {
500
- const isSelected = this.multiple
501
- ? this.values.has(option.value)
502
- : option.value === this.value;
503
- const isHighlighted = index === this.#highlightedIndex;
504
- return html `
505
- <div
506
- class="Item"
507
- role="option"
508
- id="${this.#listId}-option-${index}"
509
- aria-selected="${isSelected}"
510
- ?data-selected="${isSelected}"
511
- ?data-highlighted="${isHighlighted}"
512
- @click="${() => this.#onItemClick(option)}"
513
- >
514
- <span class="ItemText">${option.label}</span>
515
- <span class="ItemIndicator">
516
- ${isSelected ? html `<dui-icon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></dui-icon>` : nothing}
517
- </span>
518
- </div>
519
- `;
520
- };
521
- render() {
522
- const inputHtml = html `
523
- <input
524
- class="Input"
525
- id="${this.#inputId}"
526
- type="text"
527
- role="combobox"
528
- autocomplete="off"
529
- aria-haspopup="listbox"
530
- aria-expanded="${this.#popup.isOpen}"
531
- aria-controls="${this.#listId}"
532
- aria-activedescendant="${this.#highlightedIndex >= 0
533
- ? `${this.#listId}-option-${this.#highlightedIndex}`
534
- : nothing}"
535
- .value="${live(this.#inputValue)}"
536
- .placeholder="${this.placeholder}"
537
- ?disabled="${this.disabled}"
538
- @input="${this.#onInput}"
539
- @focus="${this.#onInputFocus}"
540
- @keydown="${this.#onInputKeyDown}"
541
- />
542
- `;
543
- if (this.multiple) {
544
- return html `
545
- <div
546
- class="Chips"
547
- part="chips"
548
- ?data-disabled="${this.disabled}"
549
- @click="${this.#onChipsClick}"
550
- >
551
- ${repeat(Array.from(this.values), (v) => v, this.#renderChip)}
552
- ${inputHtml}
553
- <dui-icon class="Arrow"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></dui-icon>
554
- </div>
555
- `;
556
- }
557
- return html `
558
- <div class="InputWrapper" part="input-wrapper">
559
- ${inputHtml}
560
- <dui-icon class="Arrow"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></dui-icon>
561
- </div>
562
- `;
563
- }
564
- };
565
- })();
566
- export { DuiCombobox };
131
+ .List {
132
+ padding: var(--space-1);
133
+ }
134
+
135
+ .Item {
136
+ gap: var(--space-2);
137
+ padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
138
+ border-radius: var(--radius-sm);
139
+ font-size: var(--text-sm); line-height: var(--text-sm--line-height);
140
+ font-family: var(--font-sans);
141
+ color: var(--text-1);
142
+ }
143
+
144
+ .Item:hover,
145
+ .Item[data-highlighted] {
146
+ background: oklch(from var(--foreground) l c h / 0.05);
147
+ color: var(--text-1);
148
+ }
149
+
150
+ .ItemIndicator {
151
+ --icon-size: var(--space-3_5);
152
+ }
153
+
154
+ .Empty {
155
+ padding: var(--space-3);
156
+ font-size: var(--text-sm); line-height: var(--text-sm--line-height);
157
+ color: var(--text-2);
158
+ text-align: center;
159
+ }
160
+ `;
161
+ export class DuiCombobox extends DuiComboboxPrimitive {
162
+ static styles = [...DuiComboboxPrimitive.styles, styles];
163
+ }
164
+ customElements.define(DuiCombobox.tagName, DuiCombobox);