@dryui/ui 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/accordion/accordion-content.svelte +1 -1
  2. package/dist/alert/alert.svelte +1 -1
  3. package/dist/app-frame/app-frame.svelte +125 -0
  4. package/dist/app-frame/app-frame.svelte.d.ts +10 -0
  5. package/dist/app-frame/index.d.ts +8 -0
  6. package/dist/app-frame/index.js +1 -0
  7. package/dist/aurora/aurora.svelte +22 -59
  8. package/dist/beam/beam.svelte +28 -9
  9. package/dist/carousel/carousel-button-dots.svelte +25 -8
  10. package/dist/carousel/carousel-button-thumbnails.svelte +25 -8
  11. package/dist/carousel/carousel-root.svelte +115 -4
  12. package/dist/carousel/carousel-slide.svelte +5 -1
  13. package/dist/carousel/carousel-viewport.svelte +2 -0
  14. package/dist/carousel/context.svelte.d.ts +5 -0
  15. package/dist/chart/chart-bars.svelte +25 -16
  16. package/dist/chart/chart-donut.svelte +25 -16
  17. package/dist/chart/chart-root.svelte +134 -30
  18. package/dist/chart/chart-root.svelte.d.ts +1 -0
  19. package/dist/chart/context.svelte.d.ts +3 -1
  20. package/dist/chart/context.svelte.js +1 -0
  21. package/dist/chart/index.d.ts +1 -0
  22. package/dist/chromatic-shift/chromatic-shift.svelte +36 -9
  23. package/dist/collapsible/collapsible-content.svelte +2 -1
  24. package/dist/combobox/combobox-content.svelte +26 -44
  25. package/dist/combobox/combobox-content.svelte.d.ts +1 -1
  26. package/dist/combobox/combobox-input-root.svelte +7 -1
  27. package/dist/combobox/combobox-input.svelte +21 -8
  28. package/dist/country-select/country-select-button-input.svelte +124 -260
  29. package/dist/date-picker/datepicker-content.svelte +18 -26
  30. package/dist/date-picker/datepicker-content.svelte.d.ts +2 -1
  31. package/dist/date-picker/datepicker-input-root.svelte +7 -1
  32. package/dist/date-range-picker/date-range-picker-content.svelte +18 -14
  33. package/dist/date-range-picker/date-range-picker-content.svelte.d.ts +2 -1
  34. package/dist/date-range-picker/date-range-picker-root.svelte +7 -1
  35. package/dist/displacement/displacement.svelte +16 -22
  36. package/dist/drag-and-drop/context.svelte.d.ts +2 -0
  37. package/dist/drag-and-drop/drag-and-drop-handle.svelte +34 -5
  38. package/dist/drag-and-drop/drag-and-drop-item.svelte +23 -14
  39. package/dist/drag-and-drop/drag-and-drop-root.svelte +60 -16
  40. package/dist/god-rays/god-rays.svelte +11 -0
  41. package/dist/gradient-mesh/gradient-mesh.svelte +27 -5
  42. package/dist/hover-card/context.svelte.d.ts +1 -10
  43. package/dist/hover-card/context.svelte.js +1 -2
  44. package/dist/hover-card/hover-card-content.svelte +41 -3
  45. package/dist/hover-card/hover-card-root.svelte +7 -55
  46. package/dist/hover-card/hover-card-trigger.svelte +79 -40
  47. package/dist/hover-card/hover-card-trigger.svelte.d.ts +1 -1
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.js +1 -0
  50. package/dist/internal/motion.d.ts +1 -1
  51. package/dist/internal/motion.js +1 -1
  52. package/dist/marquee/marquee.svelte +42 -5
  53. package/dist/mega-menu/context.svelte.d.ts +2 -1
  54. package/dist/mega-menu/mega-menu-button-trigger.svelte +2 -14
  55. package/dist/mega-menu/mega-menu-item.svelte +3 -1
  56. package/dist/mega-menu/mega-menu-panel.svelte +35 -3
  57. package/dist/mega-menu/mega-menu-root.svelte +28 -13
  58. package/dist/menubar/context.svelte.d.ts +2 -2
  59. package/dist/menubar/menubar-button-trigger.svelte +5 -3
  60. package/dist/menubar/menubar-content.svelte +20 -12
  61. package/dist/menubar/menubar-root.svelte +4 -4
  62. package/dist/multi-select-combobox/multi-select-combobox-content.svelte +18 -55
  63. package/dist/multi-select-combobox/multi-select-combobox-content.svelte.d.ts +1 -1
  64. package/dist/noise/noise.svelte +38 -6
  65. package/dist/notification-center/context.svelte.d.ts +0 -1
  66. package/dist/notification-center/notification-center-panel.svelte +54 -35
  67. package/dist/notification-center/notification-center-root.svelte +0 -1
  68. package/dist/notification-center/notification-center-trigger-button.svelte +1 -8
  69. package/dist/option-picker/option-picker-description.svelte +2 -2
  70. package/dist/option-picker/option-picker-item.svelte +10 -3
  71. package/dist/option-picker/option-picker-label.svelte +2 -2
  72. package/dist/option-picker/option-picker-preview.svelte +18 -13
  73. package/dist/phone-input/phone-input-select.svelte +2 -152
  74. package/dist/phone-input/phone-input-select.svelte.d.ts +1 -7
  75. package/dist/rich-text-editor/rich-text-editor-toolbar-button-input.svelte +84 -29
  76. package/dist/scroll-area/scroll-area.svelte +16 -4
  77. package/dist/select/select-content.svelte +21 -31
  78. package/dist/select/select-content.svelte.d.ts +1 -1
  79. package/dist/select/select-root-input.svelte +7 -1
  80. package/dist/shimmer/shimmer.svelte +22 -12
  81. package/dist/transfer/transfer-item.svelte +0 -3
  82. package/dist/transfer/transfer-list-input.svelte +1 -6
  83. package/dist/tree/context.svelte.d.ts +7 -1
  84. package/dist/tree/tree-item-children.svelte +12 -10
  85. package/dist/tree/tree-item-label.svelte +6 -17
  86. package/dist/tree/tree-item-label.svelte.d.ts +2 -2
  87. package/dist/tree/tree-item.svelte +28 -1
  88. package/dist/tree/tree-root.svelte +135 -59
  89. package/package.json +8 -2
  90. package/skills/dryui/SKILL.md +1 -0
  91. package/dist/hover-card/hover-card-root.svelte.d.ts +0 -9
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
+ import { fromAction } from 'svelte/attachments';
2
3
  import type { Snippet } from 'svelte';
3
4
  import type { HTMLAttributes } from 'svelte/elements';
4
- import { createAnchorPosition } from '@dryui/primitives';
5
- import type { Placement } from '@dryui/primitives';
5
+ import { createAnchoredPopover, createDismiss, type Placement } from '@dryui/primitives';
6
6
  import { getMultiSelectComboboxCtx } from './context.svelte.js';
7
7
 
8
8
  interface Props extends HTMLAttributes<HTMLDivElement> {
@@ -28,29 +28,6 @@
28
28
 
29
29
  let el = $state<HTMLDivElement | null>(null);
30
30
 
31
- const anchor = createAnchorPosition(
32
- () => ctx.anchorEl,
33
- () => el ?? null,
34
- {
35
- get placement() {
36
- return placement;
37
- },
38
- get offset() {
39
- return offset;
40
- }
41
- }
42
- );
43
-
44
- $effect(() => {
45
- if (!el) return;
46
-
47
- el.style.cssText = typeof style === 'string' ? style : '';
48
- const positionStyles = anchor.styles;
49
- for (const [key, value] of Object.entries(positionStyles)) {
50
- el.style.setProperty(key, value);
51
- }
52
- });
53
-
54
31
  function attachContent(node: HTMLDivElement) {
55
32
  el = node;
56
33
 
@@ -61,41 +38,26 @@
61
38
  };
62
39
  }
63
40
 
64
- function syncPopover(isOpen: boolean) {
65
- return (node: HTMLDivElement) => {
66
- if (isOpen && !node.matches(':popover-open')) {
67
- node.showPopover();
68
- } else if (!isOpen && node.matches(':popover-open')) {
69
- node.hidePopover();
70
- }
71
- };
72
- }
73
-
74
- function dismissOnOutsidePointerDown(node: HTMLDivElement) {
75
- function handlePointerDown(event: PointerEvent) {
76
- const target = event.target;
77
- if (!(target instanceof Node)) {
78
- return;
79
- }
80
-
81
- if (ctx.anchorEl?.contains(target) || node.contains(target)) {
82
- return;
83
- }
84
-
85
- ctx.close();
86
- }
41
+ const popover = createAnchoredPopover({
42
+ triggerEl: () => ctx.anchorEl,
43
+ contentEl: () => el ?? null,
44
+ open: () => ctx.open,
45
+ placement: () => placement,
46
+ offset: () => offset
47
+ });
87
48
 
88
- document.addEventListener('pointerdown', handlePointerDown);
89
- return () => {
90
- document.removeEventListener('pointerdown', handlePointerDown);
91
- };
92
- }
49
+ createDismiss({
50
+ enabled: () => ctx.open,
51
+ escapeKey: false,
52
+ onDismiss: () => ctx.close(),
53
+ contentEl: () => el ?? null,
54
+ triggerEl: () => ctx.anchorEl
55
+ });
93
56
  </script>
94
57
 
95
58
  <div
96
59
  {@attach attachContent}
97
- {@attach syncPopover(ctx.open)}
98
- {@attach ctx.open && dismissOnOutsidePointerDown}
60
+ {@attach fromAction(popover.applyPosition, () => style)}
99
61
  popover="manual"
100
62
  role="listbox"
101
63
  id={ctx.contentId}
@@ -123,6 +85,7 @@
123
85
  [data-multi-select-content] {
124
86
  inset: unset;
125
87
  margin: 0;
88
+ grid-template-columns: minmax(anchor-size(inline), max-content);
126
89
  background: var(--dry-color-bg-overlay);
127
90
  border: 1px solid var(--dry-color-stroke-weak);
128
91
  border-radius: var(--dry-radius-md);
@@ -1,6 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
- import type { Placement } from '@dryui/primitives';
3
+ import { type Placement } from '@dryui/primitives';
4
4
  interface Props extends HTMLAttributes<HTMLDivElement> {
5
5
  placement?: Placement;
6
6
  offset?: number;
@@ -2,7 +2,11 @@
2
2
  import { onMount } from 'svelte';
3
3
  import type { Snippet } from 'svelte';
4
4
  import type { HTMLAttributes } from 'svelte/elements';
5
- import { observeReducedMotionPreference } from '@dryui/primitives/internal/motion';
5
+ import {
6
+ observeInViewport,
7
+ observePageVisibility,
8
+ observeReducedMotionPreference
9
+ } from '@dryui/primitives/internal/motion';
6
10
 
7
11
  interface Props extends HTMLAttributes<HTMLDivElement> {
8
12
  opacity?: number;
@@ -24,15 +28,25 @@
24
28
  }: Props = $props();
25
29
 
26
30
  let prefersReducedMotion = $state(false);
31
+ let onScreen = $state(true);
32
+ let tabVisible = $state(true);
27
33
 
28
- onMount(() =>
29
- observeReducedMotionPreference((matches) => {
34
+ onMount(() => {
35
+ const stopMotion = observeReducedMotionPreference((matches) => {
30
36
  prefersReducedMotion = matches;
31
- })
32
- );
37
+ });
38
+ const stopVisibility = observePageVisibility((visible) => {
39
+ tabVisible = visible;
40
+ });
41
+ return () => {
42
+ stopMotion();
43
+ stopVisibility();
44
+ };
45
+ });
33
46
 
34
47
  const normalizedOpacity = $derived(`${Math.max(0, Math.min(1, opacity))}`);
35
48
  const shouldAnimate = $derived(animated && !prefersReducedMotion);
49
+ const paused = $derived(!onScreen || !tabVisible);
36
50
 
37
51
  function applyStyles(node: HTMLElement) {
38
52
  $effect(() => {
@@ -40,6 +54,16 @@
40
54
  node.style.setProperty('--dry-noise-opacity', normalizedOpacity);
41
55
  node.style.setProperty('--dry-noise-blend', blend);
42
56
  });
57
+
58
+ $effect(() =>
59
+ observeInViewport(
60
+ node,
61
+ (inView) => {
62
+ onScreen = inView;
63
+ },
64
+ { rootMargin: '200px' }
65
+ )
66
+ );
43
67
  }
44
68
  </script>
45
69
 
@@ -48,6 +72,7 @@
48
72
  data-noise
49
73
  data-animated={shouldAnimate || undefined}
50
74
  data-reduced-motion={prefersReducedMotion || undefined}
75
+ data-paused={paused || undefined}
51
76
  data-grain={grain}
52
77
  {...rest}
53
78
  {@attach applyStyles}
@@ -95,10 +120,17 @@
95
120
  }
96
121
 
97
122
  [data-noise][data-animated] [data-noise-texture] {
98
- will-change: transform;
99
123
  animation: noise-drift 1.6s steps(6) infinite;
100
124
  }
101
125
 
126
+ [data-noise][data-animated]:not([data-paused]) [data-noise-texture] {
127
+ will-change: transform;
128
+ }
129
+
130
+ [data-noise][data-animated][data-paused] [data-noise-texture] {
131
+ animation-play-state: paused;
132
+ }
133
+
102
134
  [data-noise][data-reduced-motion] [data-noise-texture] {
103
135
  animation: none;
104
136
  }
@@ -10,7 +10,6 @@ export interface NotificationCenterContext {
10
10
  readonly open: boolean;
11
11
  readonly triggerId: string;
12
12
  readonly panelId: string;
13
- triggerEl: HTMLElement | null;
14
13
  markAllRead: () => void;
15
14
  markRead: (id: string) => void;
16
15
  remove: (id: string) => void;
@@ -1,7 +1,8 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
+ import { fromAction } from 'svelte/attachments';
3
4
  import type { HTMLAttributes } from 'svelte/elements';
4
- import { useAnchorStyles } from '../utils/use-anchor-styles.svelte.js';
5
+ import { createAnchoredPopover } from '@dryui/primitives';
5
6
  import { getNotificationCenterCtx } from './context.svelte.js';
6
7
 
7
8
  interface Props extends HTMLAttributes<HTMLDivElement> {
@@ -33,54 +34,68 @@
33
34
 
34
35
  const ctx = getNotificationCenterCtx();
35
36
 
36
- let panelEl = $state<HTMLDivElement>();
37
+ let panelEl = $state<HTMLDivElement | null>(null);
38
+ const triggerEl = $derived(document.getElementById(ctx.triggerId) as HTMLElement | null);
37
39
 
38
- const anchor = useAnchorStyles({
39
- triggerEl: () => ctx.triggerEl,
40
- contentEl: () => panelEl ?? null,
41
- placement: () => placement,
42
- offset: () => offset
43
- });
40
+ function attachPanel(node: HTMLDivElement) {
41
+ panelEl = node;
44
42
 
45
- $effect(() => {
46
- if (!panelEl) return;
43
+ return () => {
44
+ if (panelEl === node) {
45
+ panelEl = null;
46
+ }
47
+ };
48
+ }
47
49
 
50
+ function focusTrigger() {
51
+ if (triggerEl instanceof HTMLElement) {
52
+ triggerEl.focus();
53
+ }
54
+ }
55
+
56
+ function handleClose(restoreFocus: boolean) {
48
57
  if (ctx.open) {
49
- try {
50
- if (!panelEl.matches(':popover-open')) {
51
- panelEl.showPopover();
52
- }
53
- } catch {
54
- // Already shown
55
- }
58
+ ctx.close();
59
+ }
60
+ if (restoreFocus) {
61
+ requestAnimationFrame(() => focusTrigger());
62
+ }
63
+ }
56
64
 
57
- // Nudge panel into viewport if anchor positioning overflows
65
+ function handleKeydown(event: KeyboardEvent) {
66
+ if (event.key !== 'Escape') return;
67
+ event.preventDefault();
68
+ event.stopPropagation();
69
+ handleClose(true);
70
+ }
71
+
72
+ const popover = createAnchoredPopover({
73
+ triggerEl: () => triggerEl,
74
+ contentEl: () => panelEl ?? null,
75
+ open: () => ctx.open,
76
+ placement: () => placement,
77
+ offset: () => offset,
78
+ onAfterShow: (node) => {
58
79
  requestAnimationFrame(() => {
59
- if (!panelEl) return;
60
- panelEl.style.translate = '';
61
- const rect = panelEl.getBoundingClientRect();
80
+ node.style.translate = '';
81
+ const rect = node.getBoundingClientRect();
62
82
  const pad = 8;
63
83
  if (rect.left < pad) {
64
- panelEl.style.translate = `${pad - rect.left}px 0`;
84
+ node.style.translate = `${pad - rect.left}px 0`;
65
85
  } else if (rect.right > window.innerWidth - pad) {
66
- panelEl.style.translate = `${window.innerWidth - pad - rect.right}px 0`;
86
+ node.style.translate = `${window.innerWidth - pad - rect.right}px 0`;
67
87
  }
68
88
  });
69
- } else {
70
- try {
71
- if (panelEl.matches(':popover-open')) {
72
- panelEl.hidePopover();
73
- }
74
- } catch {
75
- // Already hidden
76
- }
77
- if (panelEl) panelEl.style.translate = '';
89
+ },
90
+ onAfterHide: (node) => {
91
+ node.style.translate = '';
78
92
  }
79
93
  });
80
94
  </script>
81
95
 
82
96
  <div
83
- bind:this={panelEl}
97
+ {@attach attachPanel}
98
+ {@attach fromAction(popover.applyPosition, () => style)}
84
99
  id={ctx.panelId}
85
100
  popover="auto"
86
101
  role="region"
@@ -88,15 +103,19 @@
88
103
  data-notification-center-panel
89
104
  data-state={ctx.open ? 'open' : 'closed'}
90
105
  class={className}
91
- use:anchor.applyPosition={style}
92
106
  ontoggle={(e) => {
93
107
  const event = /** @type {ToggleEvent} */ (e);
94
108
  if (event.newState === 'open') {
95
109
  ctx.show();
96
110
  } else {
97
- ctx.close();
111
+ const restoreFocus =
112
+ panelEl instanceof HTMLElement &&
113
+ document.activeElement instanceof HTMLElement &&
114
+ panelEl.contains(document.activeElement);
115
+ handleClose(restoreFocus);
98
116
  }
99
117
  }}
118
+ onkeydown={handleKeydown}
100
119
  {...rest}
101
120
  >
102
121
  {@render children()}
@@ -36,7 +36,6 @@
36
36
  get panelId() {
37
37
  return panelId;
38
38
  },
39
- triggerEl: null,
40
39
  markAllRead() {
41
40
  items = items.map((item) => ({ ...item, read: true }));
42
41
  },
@@ -11,13 +11,6 @@
11
11
  let { children, onclick, ...rest }: Props = $props();
12
12
 
13
13
  const ctx = getNotificationCenterCtx();
14
-
15
- $effect(() => {
16
- const el = document.getElementById(ctx.triggerId);
17
- if (el) {
18
- ctx.triggerEl = el as HTMLButtonElement;
19
- }
20
- });
21
14
  </script>
22
15
 
23
16
  <Button
@@ -25,8 +18,8 @@
25
18
  type="button"
26
19
  id={ctx.triggerId}
27
20
  popovertarget={ctx.panelId}
21
+ aria-controls={ctx.panelId}
28
22
  aria-expanded={ctx.open}
29
- aria-haspopup="dialog"
30
23
  data-notification-center-trigger
31
24
  {onclick}
32
25
  {...rest}
@@ -17,8 +17,8 @@
17
17
  [data-option-picker-description] {
18
18
  grid-column: var(--dry-option-picker-description-column, 2);
19
19
  grid-row: var(--dry-option-picker-description-row, 2);
20
- font-size: var(--dry-type-small-size);
21
- line-height: 1.35;
20
+ font-size: var(--dry-option-picker-description-size, var(--dry-type-small-size));
21
+ line-height: var(--dry-option-picker-description-line-height, 1.35);
22
22
  color: var(--dry-color-text-weak);
23
23
  text-wrap: pretty;
24
24
  }
@@ -193,9 +193,16 @@
193
193
  .content {
194
194
  display: grid;
195
195
  grid-template-columns: auto minmax(0, 1fr);
196
- align-items: center;
196
+ align-items: var(--dry-option-picker-content-align, center);
197
197
  justify-items: start;
198
- gap: var(--dry-option-picker-item-gap, var(--dry-space-3));
198
+ column-gap: var(
199
+ --dry-option-picker-item-column-gap,
200
+ var(--dry-option-picker-item-gap, var(--dry-space-3))
201
+ );
202
+ row-gap: var(
203
+ --dry-option-picker-item-row-gap,
204
+ var(--dry-option-picker-item-gap, var(--dry-space-3))
205
+ );
199
206
  padding: var(--dry-option-picker-padding-y, var(--dry-space-3))
200
207
  var(--dry-option-picker-padding-x, var(--dry-space-3));
201
208
  min-block-size: var(--dry-option-picker-min-block-size, 3.5rem);
@@ -227,7 +234,7 @@
227
234
  }
228
235
 
229
236
  .root[data-size='compact'] .content {
230
- min-block-size: 2.75rem;
237
+ min-block-size: var(--dry-option-picker-compact-min-block-size, 2.75rem);
231
238
  }
232
239
 
233
240
  .root[data-size='visual'] .content {
@@ -17,8 +17,8 @@
17
17
  [data-option-picker-label] {
18
18
  grid-column: var(--dry-option-picker-label-column, 2);
19
19
  grid-row: var(--dry-option-picker-label-row, 1);
20
- font-size: var(--dry-type-small-size);
20
+ font-size: var(--dry-option-picker-label-size, var(--dry-type-small-size));
21
21
  font-weight: 600;
22
- line-height: 1.2;
22
+ line-height: var(--dry-option-picker-label-line-height, 1.2);
23
23
  }
24
24
  </style>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
+ import type { Attachment } from 'svelte/attachments';
3
4
  import type { HTMLAttributes } from 'svelte/elements';
4
5
 
5
6
  interface Props extends HTMLAttributes<HTMLSpanElement> {
@@ -11,20 +12,23 @@
11
12
 
12
13
  let { color, shape = 'rounded', variant = 'default', children, ...rest }: Props = $props();
13
14
 
14
- let el: HTMLSpanElement | undefined = $state();
15
-
16
- $effect(() => {
17
- if (!el) return;
18
- if (color) {
19
- el.style.setProperty('--dry-option-picker-preview-bg', color);
20
- } else {
21
- el.style.removeProperty('--dry-option-picker-preview-bg');
22
- }
23
- });
15
+ function applyColor(value?: string): Attachment<HTMLSpanElement> {
16
+ return (node) => {
17
+ if (value) {
18
+ node.style.setProperty('--dry-option-picker-preview-bg', value);
19
+ } else {
20
+ node.style.removeProperty('--dry-option-picker-preview-bg');
21
+ }
22
+
23
+ return () => {
24
+ node.style.removeProperty('--dry-option-picker-preview-bg');
25
+ };
26
+ };
27
+ }
24
28
  </script>
25
29
 
26
30
  <span
27
- bind:this={el}
31
+ {@attach applyColor(color)}
28
32
  data-option-picker-preview
29
33
  data-option-picker-preview-shape={shape}
30
34
  data-variant={variant !== 'default' ? variant : undefined}
@@ -39,9 +43,10 @@
39
43
  grid-column: var(--dry-option-picker-preview-column, 1);
40
44
  grid-row: var(--dry-option-picker-preview-row, 1 / span 3);
41
45
  place-items: center;
42
- align-self: center;
46
+ align-self: var(--dry-option-picker-preview-align-self, center);
43
47
  block-size: var(--dry-option-picker-preview-size, 2.25rem);
44
48
  aspect-ratio: 1;
49
+ margin-block-start: var(--dry-option-picker-preview-offset-block-start, 0);
45
50
  padding: var(--dry-option-picker-preview-padding, 0);
46
51
  border: 1px solid var(--dry-option-picker-preview-border, var(--dry-color-stroke-weak));
47
52
  border-radius: var(--dry-option-picker-preview-radius, var(--dry-radius-md));
@@ -75,7 +80,7 @@
75
80
  var(--_preset-color) 46%,
76
81
  var(--dry-color-stroke-weak) 54%
77
82
  );
78
- --dry-option-picker-preview-size: 2.75rem;
83
+ --dry-option-picker-preview-size: var(--dry-option-picker-preview-preset-size, 2.75rem);
79
84
  background: linear-gradient(
80
85
  155deg,
81
86
  color-mix(in srgb, white 18%, var(--_preset-color) 82%) 0%,
@@ -1,13 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
-
4
- interface CountryInfo {
5
- code: string;
6
- name: string;
7
- dialCode: string;
8
- flag: string;
9
- format?: string;
10
- }
3
+ import { COUNTRY_DATA, type CountryInfo } from '@dryui/primitives';
11
4
 
12
5
  interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'onchange'> {
13
6
  value?: string;
@@ -33,150 +26,7 @@
33
26
  ...rest
34
27
  }: Props = $props();
35
28
 
36
- const defaultCountries: CountryInfo[] = [
37
- {
38
- code: 'US',
39
- name: 'United States',
40
- dialCode: '+1',
41
- flag: '\u{1F1FA}\u{1F1F8}',
42
- format: '### ### ####'
43
- },
44
- {
45
- code: 'GB',
46
- name: 'United Kingdom',
47
- dialCode: '+44',
48
- flag: '\u{1F1EC}\u{1F1E7}',
49
- format: '#### ######'
50
- },
51
- {
52
- code: 'CA',
53
- name: 'Canada',
54
- dialCode: '+1',
55
- flag: '\u{1F1E8}\u{1F1E6}',
56
- format: '### ### ####'
57
- },
58
- {
59
- code: 'AU',
60
- name: 'Australia',
61
- dialCode: '+61',
62
- flag: '\u{1F1E6}\u{1F1FA}',
63
- format: '### ### ###'
64
- },
65
- {
66
- code: 'DE',
67
- name: 'Germany',
68
- dialCode: '+49',
69
- flag: '\u{1F1E9}\u{1F1EA}',
70
- format: '### #######'
71
- },
72
- {
73
- code: 'FR',
74
- name: 'France',
75
- dialCode: '+33',
76
- flag: '\u{1F1EB}\u{1F1F7}',
77
- format: '# ## ## ## ##'
78
- },
79
- {
80
- code: 'IT',
81
- name: 'Italy',
82
- dialCode: '+39',
83
- flag: '\u{1F1EE}\u{1F1F9}',
84
- format: '### ### ####'
85
- },
86
- {
87
- code: 'ES',
88
- name: 'Spain',
89
- dialCode: '+34',
90
- flag: '\u{1F1EA}\u{1F1F8}',
91
- format: '### ## ## ##'
92
- },
93
- {
94
- code: 'BR',
95
- name: 'Brazil',
96
- dialCode: '+55',
97
- flag: '\u{1F1E7}\u{1F1F7}',
98
- format: '## ##### ####'
99
- },
100
- {
101
- code: 'IN',
102
- name: 'India',
103
- dialCode: '+91',
104
- flag: '\u{1F1EE}\u{1F1F3}',
105
- format: '##### #####'
106
- },
107
- {
108
- code: 'CN',
109
- name: 'China',
110
- dialCode: '+86',
111
- flag: '\u{1F1E8}\u{1F1F3}',
112
- format: '### #### ####'
113
- },
114
- {
115
- code: 'JP',
116
- name: 'Japan',
117
- dialCode: '+81',
118
- flag: '\u{1F1EF}\u{1F1F5}',
119
- format: '## #### ####'
120
- },
121
- {
122
- code: 'KR',
123
- name: 'South Korea',
124
- dialCode: '+82',
125
- flag: '\u{1F1F0}\u{1F1F7}',
126
- format: '## #### ####'
127
- },
128
- {
129
- code: 'MX',
130
- name: 'Mexico',
131
- dialCode: '+52',
132
- flag: '\u{1F1F2}\u{1F1FD}',
133
- format: '## #### ####'
134
- },
135
- {
136
- code: 'RU',
137
- name: 'Russia',
138
- dialCode: '+7',
139
- flag: '\u{1F1F7}\u{1F1FA}',
140
- format: '### ### ## ##'
141
- },
142
- {
143
- code: 'SA',
144
- name: 'Saudi Arabia',
145
- dialCode: '+966',
146
- flag: '\u{1F1F8}\u{1F1E6}',
147
- format: '## ### ####'
148
- },
149
- {
150
- code: 'AE',
151
- name: 'United Arab Emirates',
152
- dialCode: '+971',
153
- flag: '\u{1F1E6}\u{1F1EA}',
154
- format: '## ### ####'
155
- },
156
- {
157
- code: 'SG',
158
- name: 'Singapore',
159
- dialCode: '+65',
160
- flag: '\u{1F1F8}\u{1F1EC}',
161
- format: '#### ####'
162
- },
163
- {
164
- code: 'NL',
165
- name: 'Netherlands',
166
- dialCode: '+31',
167
- flag: '\u{1F1F3}\u{1F1F1}',
168
- format: '# ########'
169
- },
170
- {
171
- code: 'SE',
172
- name: 'Sweden',
173
- dialCode: '+46',
174
- flag: '\u{1F1F8}\u{1F1EA}',
175
- format: '## ### ## ##'
176
- }
177
- ];
178
-
179
- const countries = $derived(countriesProp ?? defaultCountries);
29
+ const countries = $derived(countriesProp ?? COUNTRY_DATA);
180
30
  let manualCountryCode = $derived(defaultCountry);
181
31
 
182
32
  const orderedCountries = $derived(
@@ -1,11 +1,5 @@
1
1
  import type { HTMLAttributes } from 'svelte/elements';
2
- interface CountryInfo {
3
- code: string;
4
- name: string;
5
- dialCode: string;
6
- flag: string;
7
- format?: string;
8
- }
2
+ import { type CountryInfo } from '@dryui/primitives';
9
3
  interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'onchange'> {
10
4
  value?: string;
11
5
  defaultCountry?: string;