@dryui/primitives 0.1.12 → 0.2.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.
package/dist/index.d.ts CHANGED
@@ -68,12 +68,6 @@ export { SelectableTileGroup } from './selectable-tile-group/index.js';
68
68
  export type { SelectableTileGroupRootProps, SelectableTileGroupItemProps, SelectableTileGroupIndicatorProps, SelectableTileGroupLabelProps, SelectableTileGroupDescriptionProps, SelectableTileGroupMetaProps } from './selectable-tile-group/index.js';
69
69
  export { Container } from './container/index.js';
70
70
  export type { ContainerProps } from './container/index.js';
71
- export { Stack } from './stack/index.js';
72
- export type { StackProps } from './stack/index.js';
73
- export { Grid } from './grid/index.js';
74
- export type { GridProps } from './grid/index.js';
75
- export { Flex } from './flex/index.js';
76
- export type { FlexProps } from './flex/index.js';
77
71
  export { Separator } from './separator/index.js';
78
72
  export type { SeparatorProps } from './separator/index.js';
79
73
  export { Spacer } from './spacer/index.js';
package/dist/index.js CHANGED
@@ -38,11 +38,8 @@ export { Toggle } from './toggle/index.js';
38
38
  export { ToggleGroup } from './toggle-group/index.js';
39
39
  export { AffixGroup } from './affix-group/index.js';
40
40
  export { SelectableTileGroup } from './selectable-tile-group/index.js';
41
- // Phase 4 — Layout Primitives
41
+ // Phase 4 — Layout Utilities
42
42
  export { Container } from './container/index.js';
43
- export { Stack } from './stack/index.js';
44
- export { Grid } from './grid/index.js';
45
- export { Flex } from './flex/index.js';
46
43
  export { Separator } from './separator/index.js';
47
44
  export { Spacer } from './spacer/index.js';
48
45
  export { AspectRatio } from './aspect-ratio/index.js';
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import { getMapCtx, setMarkerCtx } from './context.svelte.js';
4
- import { onDestroy } from 'svelte';
4
+ import { onDestroy, untrack } from 'svelte';
5
5
  import type { LngLat, MapMarkerInstance, MarkerOptions } from './types.js';
6
6
 
7
7
  interface Props {
@@ -30,10 +30,10 @@
30
30
  $effect(() => {
31
31
  if (!ctx.loaded || !ctx.map || !ctx.lib) return;
32
32
 
33
- // Remove previous marker if it exists
34
- if (markerInstance) {
35
- markerInstance.remove();
36
- markerInstance = null;
33
+ // Remove previous marker without tracking markerInstance as a dependency
34
+ const prev = untrack(() => markerInstance);
35
+ if (prev) {
36
+ prev.remove();
37
37
  }
38
38
 
39
39
  const opts: MarkerOptions = {};
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import { getMapCtx, getMarkerCtx } from './context.svelte.js';
4
- import { onDestroy } from 'svelte';
4
+ import { onDestroy, untrack } from 'svelte';
5
5
  import type { MapPopupInstance } from './types.js';
6
6
 
7
7
  interface Props {
@@ -29,10 +29,10 @@
29
29
  $effect(() => {
30
30
  if (!mapCtx.loaded || !mapCtx.map || !mapCtx.lib || !markerCtx.marker || !contentEl) return;
31
31
 
32
- // Remove previous popup
33
- if (popupInstance) {
34
- popupInstance.remove();
35
- popupInstance = null;
32
+ // Remove previous popup without tracking popupInstance as a dependency
33
+ const prev = untrack(() => popupInstance);
34
+ if (prev) {
35
+ prev.remove();
36
36
  }
37
37
 
38
38
  try {
@@ -40,13 +40,11 @@
40
40
  const isDisabled = $derived(disabled || formCtx?.disabled || false);
41
41
  const hasError = $derived(formCtx?.hasError || false);
42
42
 
43
- let inputEl: HTMLInputElement | undefined = $state();
43
+ let inputEl: HTMLInputElement | undefined;
44
44
  let isFocused = $state(false);
45
45
  let mirrorSelectionStart = $state<number | null>(null);
46
46
  let mirrorSelectionEnd = $state<number | null>(null);
47
- let completeFired = $state(false);
48
47
 
49
- // Build validation regex from type or pattern prop
50
48
  const validationRegex = $derived(pattern ?? (type === 'numeric' ? /^\d+$/ : /^[a-zA-Z0-9]+$/));
51
49
 
52
50
  // Compute cells from value
@@ -95,25 +93,28 @@
95
93
  mirrorSelectionEnd = inputEl.selectionEnd;
96
94
  }
97
95
 
98
- $effect(() => {
99
- const handler = () => {
100
- if (document.activeElement === inputEl) {
101
- syncSelection();
96
+ function captureInput(node: HTMLInputElement) {
97
+ inputEl = node;
98
+ return () => {
99
+ if (inputEl === node) {
100
+ inputEl = undefined;
102
101
  }
103
102
  };
104
- document.addEventListener('selectionchange', handler);
105
- return () => document.removeEventListener('selectionchange', handler);
106
- });
103
+ }
107
104
 
108
- // Reset completeFired when value becomes incomplete
109
- $effect(() => {
110
- if (value.length < length) {
111
- completeFired = false;
105
+ function maybeFireComplete(previousValue: string, nextValue: string) {
106
+ if (nextValue.length !== length) return;
107
+ if (previousValue.length === length && previousValue === nextValue) return;
108
+
109
+ oncomplete?.(nextValue);
110
+ if (blurOnComplete) {
111
+ inputEl?.blur();
112
112
  }
113
- });
113
+ }
114
114
 
115
115
  function handleInput(e: Event) {
116
116
  const input = e.target as HTMLInputElement;
117
+ const previousValue = value;
117
118
  let newValue = input.value;
118
119
 
119
120
  // Filter by validation regex (character by character)
@@ -128,18 +129,12 @@
128
129
  value = newValue;
129
130
  syncSelection();
130
131
 
131
- // Fire oncomplete once when fully filled
132
- if (newValue.length === length && !completeFired) {
133
- completeFired = true;
134
- oncomplete?.(newValue);
135
- if (blurOnComplete) {
136
- inputEl?.blur();
137
- }
138
- }
132
+ maybeFireComplete(previousValue, newValue);
139
133
  }
140
134
 
141
135
  function handlePaste(e: ClipboardEvent) {
142
136
  e.preventDefault();
137
+ const previousValue = value;
143
138
  let pasted = e.clipboardData?.getData('text') ?? '';
144
139
  if (pasteTransformer) {
145
140
  pasted = pasteTransformer(pasted);
@@ -171,13 +166,7 @@
171
166
  syncSelection();
172
167
  });
173
168
 
174
- if (newValue.length === length && !completeFired) {
175
- completeFired = true;
176
- oncomplete?.(newValue);
177
- if (blurOnComplete) {
178
- inputEl?.blur();
179
- }
180
- }
169
+ maybeFireComplete(previousValue, newValue);
181
170
  }
182
171
 
183
172
  function handleFocus() {
@@ -219,13 +208,10 @@
219
208
  }
220
209
  </script>
221
210
 
222
- <!-- svelte-ignore a11y_role_supports_aria_props -->
223
211
  <div
224
212
  role="group"
225
213
  aria-label="PIN input"
226
214
  aria-describedby={formCtx?.describedBy}
227
- aria-invalid={hasError || undefined}
228
- aria-errormessage={formCtx?.errorMessageId}
229
215
  data-pin-input-root
230
216
  data-disabled={isDisabled || undefined}
231
217
  data-error={hasError || undefined}
@@ -235,7 +221,7 @@
235
221
  {...rest}
236
222
  >
237
223
  <input
238
- bind:this={inputEl}
224
+ {@attach captureInput}
239
225
  type="text"
240
226
  inputmode={type === 'numeric' ? 'numeric' : 'text'}
241
227
  autocomplete="one-time-code"
@@ -243,6 +229,9 @@
243
229
  {value}
244
230
  id={formCtx?.id}
245
231
  aria-label="PIN input"
232
+ aria-describedby={formCtx?.describedBy}
233
+ aria-invalid={hasError || undefined}
234
+ aria-errormessage={formCtx?.errorMessageId}
246
235
  aria-required={formCtx?.required || undefined}
247
236
  disabled={isDisabled}
248
237
  spellcheck={false}
@@ -253,6 +242,8 @@
253
242
  onfocus={handleFocus}
254
243
  onblur={handleBlur}
255
244
  onkeydown={handleKeydown}
245
+ onkeyup={syncSelection}
246
+ onselect={syncSelection}
256
247
  />
257
248
 
258
249
  {#if children}
@@ -6,7 +6,12 @@ export interface SelectRootProps {
6
6
  value?: string;
7
7
  disabled?: boolean;
8
8
  name?: string;
9
- children: Snippet;
9
+ options?: Array<string | {
10
+ value: string;
11
+ label: string;
12
+ }>;
13
+ placeholder?: string;
14
+ children?: Snippet;
10
15
  }
11
16
  export interface SelectTriggerProps extends HTMLAttributes<HTMLDivElement> {
12
17
  children: Snippet;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dryui/primitives",
3
- "version": "0.1.12",
3
+ "version": "0.2.0",
4
4
  "author": "Rob Balfre",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -266,11 +266,6 @@
266
266
  "svelte": "./dist/file-upload/index.js",
267
267
  "default": "./dist/file-upload/index.js"
268
268
  },
269
- "./flex": {
270
- "types": "./dist/flex/index.d.ts",
271
- "svelte": "./dist/flex/index.js",
272
- "default": "./dist/flex/index.js"
273
- },
274
269
  "./flip-card": {
275
270
  "types": "./dist/flip-card/index.d.ts",
276
271
  "svelte": "./dist/flip-card/index.js",
@@ -331,11 +326,6 @@
331
326
  "svelte": "./dist/gradient-mesh/index.js",
332
327
  "default": "./dist/gradient-mesh/index.js"
333
328
  },
334
- "./grid": {
335
- "types": "./dist/grid/index.d.ts",
336
- "svelte": "./dist/grid/index.js",
337
- "default": "./dist/grid/index.js"
338
- },
339
329
  "./hero": {
340
330
  "types": "./dist/hero/index.d.ts",
341
331
  "svelte": "./dist/hero/index.js",
@@ -621,11 +611,6 @@
621
611
  "svelte": "./dist/spotlight/index.js",
622
612
  "default": "./dist/spotlight/index.js"
623
613
  },
624
- "./stack": {
625
- "types": "./dist/stack/index.d.ts",
626
- "svelte": "./dist/stack/index.js",
627
- "default": "./dist/stack/index.js"
628
- },
629
614
  "./stat-card": {
630
615
  "types": "./dist/stat-card/index.d.ts",
631
616
  "svelte": "./dist/stat-card/index.js",
@@ -1021,11 +1006,6 @@
1021
1006
  "svelte": "./dist/file-upload/index.js",
1022
1007
  "default": "./dist/file-upload/index.js"
1023
1008
  },
1024
- "./flex": {
1025
- "types": "./dist/flex/index.d.ts",
1026
- "svelte": "./dist/flex/index.js",
1027
- "default": "./dist/flex/index.js"
1028
- },
1029
1009
  "./flip-card": {
1030
1010
  "types": "./dist/flip-card/index.d.ts",
1031
1011
  "svelte": "./dist/flip-card/index.js",
@@ -1086,11 +1066,6 @@
1086
1066
  "svelte": "./dist/gradient-mesh/index.js",
1087
1067
  "default": "./dist/gradient-mesh/index.js"
1088
1068
  },
1089
- "./grid": {
1090
- "types": "./dist/grid/index.d.ts",
1091
- "svelte": "./dist/grid/index.js",
1092
- "default": "./dist/grid/index.js"
1093
- },
1094
1069
  "./hero": {
1095
1070
  "types": "./dist/hero/index.d.ts",
1096
1071
  "svelte": "./dist/hero/index.js",
@@ -1376,11 +1351,6 @@
1376
1351
  "svelte": "./dist/spotlight/index.js",
1377
1352
  "default": "./dist/spotlight/index.js"
1378
1353
  },
1379
- "./stack": {
1380
- "types": "./dist/stack/index.d.ts",
1381
- "svelte": "./dist/stack/index.js",
1382
- "default": "./dist/stack/index.js"
1383
- },
1384
1354
  "./stat-card": {
1385
1355
  "types": "./dist/stat-card/index.d.ts",
1386
1356
  "svelte": "./dist/stat-card/index.js",