@iris-ui-kit/vue 0.2.20 → 0.2.22

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 (75) hide show
  1. package/dist/admin.cjs +36 -6
  2. package/dist/admin.cjs.map +1 -1
  3. package/dist/admin.js +4 -4
  4. package/dist/async.cjs +48 -2
  5. package/dist/async.cjs.map +1 -1
  6. package/dist/async.d.cts +27 -3
  7. package/dist/async.d.ts +27 -3
  8. package/dist/async.js +1 -1
  9. package/dist/chunk-25NYWSXP.js +20 -0
  10. package/dist/chunk-25NYWSXP.js.map +1 -0
  11. package/dist/{chunk-I6D5VXQK.js → chunk-3V46HGRC.js} +4 -3
  12. package/dist/chunk-3V46HGRC.js.map +1 -0
  13. package/dist/{chunk-QLUIKEMJ.js → chunk-ENKE2BPC.js} +3 -3
  14. package/dist/{chunk-QLUIKEMJ.js.map → chunk-ENKE2BPC.js.map} +1 -1
  15. package/dist/{chunk-4FLIW67H.js → chunk-IAG64CHL.js} +21 -28
  16. package/dist/chunk-IAG64CHL.js.map +1 -0
  17. package/dist/{chunk-W2JVHGFR.js → chunk-MO7AAXA6.js} +33 -13
  18. package/dist/chunk-MO7AAXA6.js.map +1 -0
  19. package/dist/chunk-NNOF7KUH.js +24 -0
  20. package/dist/chunk-NNOF7KUH.js.map +1 -0
  21. package/dist/{chunk-MMQKSFME.js → chunk-QQ25RKOO.js} +9 -5
  22. package/dist/chunk-QQ25RKOO.js.map +1 -0
  23. package/dist/chunk-SJB5DIIY.js +119 -0
  24. package/dist/chunk-SJB5DIIY.js.map +1 -0
  25. package/dist/{chunk-H7HVVPYR.js → chunk-UPC4GN3F.js} +8 -2
  26. package/dist/chunk-UPC4GN3F.js.map +1 -0
  27. package/dist/{chunk-72PZMU6R.js → chunk-ZTPIXL7Q.js} +21 -3
  28. package/dist/chunk-ZTPIXL7Q.js.map +1 -0
  29. package/dist/form.cjs +28 -23
  30. package/dist/form.cjs.map +1 -1
  31. package/dist/form.d.cts +3 -2
  32. package/dist/form.d.ts +3 -2
  33. package/dist/form.js +2 -1
  34. package/dist/index.cjs +166 -45
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.js +38 -16
  37. package/dist/index.js.map +1 -1
  38. package/dist/layouts.cjs +2 -1
  39. package/dist/layouts.cjs.map +1 -1
  40. package/dist/layouts.js +1 -1
  41. package/dist/machine.cjs +11 -4
  42. package/dist/machine.cjs.map +1 -1
  43. package/dist/machine.d.cts +12 -3
  44. package/dist/machine.d.ts +12 -3
  45. package/dist/machine.js +1 -1
  46. package/dist/provider.cjs +53 -9
  47. package/dist/provider.cjs.map +1 -1
  48. package/dist/provider.js +3 -3
  49. package/dist/resource.cjs +7 -3
  50. package/dist/resource.cjs.map +1 -1
  51. package/dist/resource.d.cts +10 -1
  52. package/dist/resource.d.ts +10 -1
  53. package/dist/resource.js +1 -1
  54. package/dist/skeletons.cjs +2 -1
  55. package/dist/skeletons.cjs.map +1 -1
  56. package/dist/skeletons.js +2 -2
  57. package/dist/skins.cjs +6 -0
  58. package/dist/skins.cjs.map +1 -1
  59. package/dist/skins.js +1 -1
  60. package/dist/theme.cjs +19 -1
  61. package/dist/theme.cjs.map +1 -1
  62. package/dist/theme.js +1 -1
  63. package/package.json +1 -1
  64. package/dist/chunk-4FLIW67H.js.map +0 -1
  65. package/dist/chunk-72PZMU6R.js.map +0 -1
  66. package/dist/chunk-H7HVVPYR.js.map +0 -1
  67. package/dist/chunk-I6D5VXQK.js.map +0 -1
  68. package/dist/chunk-MMQKSFME.js.map +0 -1
  69. package/dist/chunk-TQB5LVOH.js +0 -17
  70. package/dist/chunk-TQB5LVOH.js.map +0 -1
  71. package/dist/chunk-W2JVHGFR.js.map +0 -1
  72. package/dist/chunk-XSLBANUV.js +0 -16
  73. package/dist/chunk-XSLBANUV.js.map +0 -1
  74. package/dist/chunk-ZY4NLITM.js +0 -73
  75. package/dist/chunk-ZY4NLITM.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -80,7 +80,7 @@ var ThemeProvider = vue.defineComponent({
80
80
  },
81
81
  setup(props, { slots }) {
82
82
  const current = vue.ref(props.store.store.getState());
83
- const unsubscribe = props.store.store.subscribe((next) => {
83
+ let unsubscribe = props.store.store.subscribe((next) => {
84
84
  current.value = next;
85
85
  });
86
86
  let applied = null;
@@ -102,6 +102,24 @@ var ThemeProvider = vue.defineComponent({
102
102
  vue.watch(current, () => {
103
103
  if (applied) applyCurrent();
104
104
  });
105
+ vue.watch(
106
+ () => props.store,
107
+ (nextStore) => {
108
+ unsubscribe();
109
+ unsubscribe = nextStore.store.subscribe((next) => {
110
+ current.value = next;
111
+ });
112
+ current.value = nextStore.store.getState();
113
+ if (applied) applyCurrent();
114
+ }
115
+ );
116
+ vue.watch(
117
+ () => props.target,
118
+ () => {
119
+ if (applied) applyCurrent();
120
+ if (dirApplied) applyDir();
121
+ }
122
+ );
105
123
  vue.watch(
106
124
  () => props.dir,
107
125
  () => {
@@ -172,6 +190,12 @@ var SkinProvider = vue.defineComponent({
172
190
  vue.watch(current, () => {
173
191
  if (applied) apply();
174
192
  });
193
+ vue.watch(
194
+ () => props.target,
195
+ () => {
196
+ if (applied) apply();
197
+ }
198
+ );
175
199
  vue.onBeforeUnmount(() => {
176
200
  unsubscribe();
177
201
  applied?.revert();
@@ -202,14 +226,21 @@ function useSkin() {
202
226
  errors: engine.errors
203
227
  };
204
228
  }
205
- function useMachine(machine) {
229
+ function useMachine(machine, options = {}) {
206
230
  const state = vue.ref(machine.store.getState());
207
231
  const unsubscribe = machine.store.subscribe((next) => {
208
232
  state.value = next;
209
233
  });
210
- vue.onBeforeUnmount(() => {
211
- unsubscribe();
212
- });
234
+ vue.onScopeDispose(
235
+ () => {
236
+ unsubscribe();
237
+ if (options.stopOnUnmount !== false) machine.stop();
238
+ },
239
+ // failSilently: outside any effect scope there is nothing to dispose —
240
+ // registering is a no-op and must not emit the "no active effect scope"
241
+ // dev warning. Within a component/effectScope this arg changes nothing.
242
+ true
243
+ );
213
244
  return { state, send: machine.send };
214
245
  }
215
246
  var FormInjectionKey = /* @__PURE__ */ Symbol("IrisForm");
@@ -269,11 +300,7 @@ var IrisForm = vue.defineComponent({
269
300
  });
270
301
  function useForm(config) {
271
302
  const form = core.createFormStore(config);
272
- const state = vue.ref(form.getState());
273
- const unsubscribe = form.subscribe((next) => {
274
- state.value = next;
275
- });
276
- vue.onBeforeUnmount(unsubscribe);
303
+ const state = useStore(form.store);
277
304
  return {
278
305
  form,
279
306
  state,
@@ -298,22 +325,24 @@ function useForm(config) {
298
325
  }
299
326
  function useField(name) {
300
327
  const form = useFormContext();
301
- const state = vue.ref(form.getState());
302
- const unsubscribe = form.subscribe((next) => {
303
- state.value = next;
304
- });
305
- vue.onBeforeUnmount(unsubscribe);
306
328
  const key = core.formatPath(name);
307
- const value = vue.computed(() => core.getByPath(state.value.values, name));
308
- const error = vue.computed(() => state.value.errors[key]);
329
+ const segments = core.parsePath(name);
330
+ const valueSlice = useStoreSelector(form.store, (s) => core.getByPath(s.values, segments));
331
+ const errorSlice = useStoreSelector(form.store, (s) => s.errors[key]);
332
+ const touchedSlice = useStoreSelector(form.store, (s) => Boolean(s.touched[key]));
333
+ const dirtySlice = useStoreSelector(form.store, (s) => Boolean(s.dirty[key]));
334
+ const value = vue.computed(() => valueSlice.value);
335
+ const error = vue.computed(() => errorSlice.value);
336
+ const touched = vue.computed(() => touchedSlice.value);
337
+ const dirty = vue.computed(() => dirtySlice.value);
309
338
  return {
310
339
  name,
311
340
  value,
312
341
  error,
313
- touched: vue.computed(() => Boolean(state.value.touched[key])),
314
- dirty: vue.computed(() => Boolean(state.value.dirty[key])),
342
+ touched,
343
+ dirty,
315
344
  setValue: (next) => form.setFieldValue(name, next),
316
- setTouched: (touched = true) => form.setFieldTouched(name, touched),
345
+ setTouched: (touched2 = true) => form.setFieldTouched(name, touched2),
317
346
  fieldProps: vue.computed(() => ({
318
347
  modelValue: value.value,
319
348
  "onUpdate:modelValue": (next) => form.setFieldValue(name, next),
@@ -324,16 +353,11 @@ function useField(name) {
324
353
  }
325
354
  function useFieldArray(name) {
326
355
  const form = useFormContext();
327
- const state = vue.ref(form.getState());
328
- const unsubscribe = form.subscribe((next) => {
329
- state.value = next;
330
- });
331
- vue.onBeforeUnmount(unsubscribe);
356
+ const raw = useStoreSelector(form.store, (s) => s.values[name]);
357
+ const fields = vue.computed(() => Array.isArray(raw.value) ? raw.value : []);
332
358
  return {
333
359
  name,
334
- fields: vue.computed(
335
- () => Array.isArray(state.value.values[name]) ? state.value.values[name] : []
336
- ),
360
+ fields,
337
361
  push: (item) => form.arrayPush(name, item),
338
362
  remove: (index) => form.arrayRemove(name, index),
339
363
  insert: (index, item) => form.arrayInsert(name, index, item),
@@ -441,8 +465,31 @@ function useI18n() {
441
465
  };
442
466
  }
443
467
  function useAsyncResource(fetcher, options = {}) {
468
+ const holder = {
469
+ // isRef-only resolution. NEVER toValue() here: the element type is itself
470
+ // a function, so toValue(fetcher) would *invoke the fetcher at setup*
471
+ // (spurious request) and toValue(getter) would do the same. isRef narrows
472
+ // to the only unambiguous reactive form: ref(fetcher) / computed(() =>
473
+ // fetcher) / shallowRef(fetcher) — a ComputedRef IS a Ref.
474
+ // F3 elision point — the ONE explicit narrowing cast: after the isRef
475
+ // guard the else arm is `F | (() => F)`, and the bare-getter arm's return
476
+ // `F` (a function) is not assignable to `F` (TS2322). No runtime
477
+ // discriminant distinguishes a plain fetcher from a bare getter (both are
478
+ // functions), so the cast encodes exactly the documented F3 ambiguity and
479
+ // adds no unsafety beyond F3.
480
+ current: vue.isRef(fetcher) ? fetcher.value : fetcher
481
+ };
482
+ if (vue.isRef(fetcher)) {
483
+ vue.watch(
484
+ fetcher,
485
+ (next) => {
486
+ holder.current = next;
487
+ },
488
+ { flush: "sync" }
489
+ );
490
+ }
444
491
  const config = "initialData" in options ? { initialData: options.initialData } : {};
445
- const resource = core.createAsyncResource(fetcher, config);
492
+ const resource = core.createAsyncResource((...params) => holder.current(...params), config);
446
493
  const state = vue.ref(resource.getState());
447
494
  const unsubscribe = resource.subscribe((next) => {
448
495
  state.value = next;
@@ -470,7 +517,30 @@ function useAsyncResource(fetcher, options = {}) {
470
517
  };
471
518
  }
472
519
  function usePaginatedResource(fetcher, options = {}) {
473
- const resource = core.createPaginatedResource(fetcher, {
520
+ const holder = {
521
+ // isRef-only resolution. NEVER toValue() here: the element type is itself
522
+ // a function, so toValue(fetcher) would *invoke the fetcher at setup*
523
+ // (spurious request) and toValue(getter) would do the same. isRef narrows
524
+ // to the only unambiguous reactive form: ref(fetcher) / computed(() =>
525
+ // fetcher) / shallowRef(fetcher) — a ComputedRef IS a Ref.
526
+ // F3 elision point — the ONE explicit narrowing cast: after the isRef
527
+ // guard the else arm is `F | (() => F)`, and the bare-getter arm's return
528
+ // `F` (a function) is not assignable to `F` (TS2322). No runtime
529
+ // discriminant distinguishes a plain fetcher from a bare getter (both are
530
+ // functions), so the cast encodes exactly the documented F3 ambiguity and
531
+ // adds no unsafety beyond F3.
532
+ current: vue.isRef(fetcher) ? fetcher.value : fetcher
533
+ };
534
+ if (vue.isRef(fetcher)) {
535
+ vue.watch(
536
+ fetcher,
537
+ (next) => {
538
+ holder.current = next;
539
+ },
540
+ { flush: "sync" }
541
+ );
542
+ }
543
+ const resource = core.createPaginatedResource((query) => holder.current(query), {
474
544
  pageSize: options.pageSize,
475
545
  mode: options.mode
476
546
  });
@@ -506,10 +576,14 @@ function usePaginatedResource(fetcher, options = {}) {
506
576
  };
507
577
  }
508
578
  function useResourceController(config) {
509
- const controller = core.createResourceController(config);
579
+ const controller = core.createResourceController({ ...config, immediate: false });
580
+ const immediate = config.immediate !== false;
581
+ if (immediate) {
582
+ vue.onMounted(() => void controller.load());
583
+ }
584
+ vue.onScopeDispose(() => controller.destroy());
510
585
  const state = vue.shallowRef(controller.getState());
511
- vue.onBeforeUnmount(controller.subscribe((next) => state.value = next));
512
- vue.onBeforeUnmount(() => controller.destroy());
586
+ vue.onScopeDispose(controller.subscribe((next) => state.value = next));
513
587
  return { ...controller, state };
514
588
  }
515
589
  function useDataSource(config) {
@@ -641,7 +715,8 @@ var IrisSidebarLayout = vue.defineComponent({
641
715
  () => props.collapsed,
642
716
  (value) => {
643
717
  if (value !== void 0) internalCollapsed.value = value;
644
- }
718
+ },
719
+ { immediate: true }
645
720
  );
646
721
  const setCollapsed = (value) => {
647
722
  if (!isControlled.value) internalCollapsed.value = value;
@@ -2459,6 +2534,10 @@ var IrisAdminTabs = vue.defineComponent({
2459
2534
  onClick: (e) => {
2460
2535
  e.stopPropagation();
2461
2536
  close(tab.key);
2537
+ const root = e.currentTarget.closest(
2538
+ '[role="tablist"]'
2539
+ );
2540
+ void vue.nextTick(() => focusTab(root, props.nav.getState().activeKey));
2462
2541
  }
2463
2542
  },
2464
2543
  [vue.h(IrisIcon, { name: "x", size: 12 })]
@@ -3042,25 +3121,45 @@ var IrisProvider = vue.defineComponent({
3042
3121
  target: { type: Object, default: null }
3043
3122
  },
3044
3123
  setup(props, { slots }) {
3045
- const collected = core.runPlugins(props.plugins ?? []);
3124
+ const collected = vue.shallowRef(core.runPlugins(props.plugins ?? []));
3125
+ const ctx = vue.shallowReactive({
3126
+ stores: collected.value.stores,
3127
+ installed: new Set((props.plugins ?? []).map((p) => p.name))
3128
+ });
3129
+ vue.provide(PluginStoreContextKey, ctx);
3046
3130
  let applied = null;
3131
+ let mounted = false;
3047
3132
  vue.onMounted(() => {
3133
+ mounted = true;
3048
3134
  if (typeof document === "undefined") return;
3049
3135
  const el = props.target ?? document.documentElement;
3050
- applied = theme.applyCssVars(Object.entries(collected.tokens), el);
3136
+ applied = theme.applyCssVars(Object.entries(collected.value.tokens), el);
3051
3137
  });
3138
+ vue.watch(
3139
+ () => props.plugins,
3140
+ (next) => {
3141
+ const prev = collected.value;
3142
+ const nextCollected = core.runPlugins(next ?? []);
3143
+ applied?.revert();
3144
+ applied = null;
3145
+ prev.teardown();
3146
+ collected.value = nextCollected;
3147
+ ctx.stores = nextCollected.stores;
3148
+ ctx.installed = new Set((next ?? []).map((p) => p.name));
3149
+ if (mounted && typeof document !== "undefined") {
3150
+ const el = props.target ?? document.documentElement;
3151
+ applied = theme.applyCssVars(Object.entries(nextCollected.tokens), el);
3152
+ }
3153
+ }
3154
+ );
3052
3155
  vue.onBeforeUnmount(() => {
3053
3156
  applied?.revert();
3054
3157
  applied = null;
3055
- collected.teardown();
3056
- });
3057
- vue.provide(PluginStoreContextKey, {
3058
- stores: collected.stores,
3059
- installed: new Set((props.plugins ?? []).map((p) => p.name))
3158
+ collected.value.teardown();
3060
3159
  });
3061
3160
  return () => {
3062
3161
  const locale = props.locale ?? DEFAULT_LOCALE;
3063
- const messages = { ...collected.messages[locale], ...props.messages ?? {} };
3162
+ const messages = { ...collected.value.messages[locale], ...props.messages ?? {} };
3064
3163
  let tree = vue.h(
3065
3164
  IrisI18nProvider,
3066
3165
  { locale: props.locale, messages },
@@ -6255,6 +6354,7 @@ var IrisList = vue.defineComponent({
6255
6354
  isEnabled
6256
6355
  });
6257
6356
  const activeIndex = vue.ref(nav.index);
6357
+ const hoveredIndex = vue.ref(-1);
6258
6358
  vue.watch(
6259
6359
  () => props.items,
6260
6360
  () => {
@@ -6337,7 +6437,7 @@ var IrisList = vue.defineComponent({
6337
6437
  cursor: item.disabled ? "not-allowed" : "pointer",
6338
6438
  opacity: item.disabled ? "0.5" : "1",
6339
6439
  fontSize: "14px",
6340
- background: selected ? "var(--iris-primary)" : active ? "var(--iris-surface-hover)" : "transparent",
6440
+ background: selected ? "var(--iris-primary)" : hoveredIndex.value === index ? "var(--iris-surface-hover)" : active ? "var(--iris-surface-hover)" : "transparent",
6341
6441
  color: selected ? "var(--iris-primary-foreground)" : "var(--iris-foreground)",
6342
6442
  outline: "none"
6343
6443
  };
@@ -6358,8 +6458,15 @@ var IrisList = vue.defineComponent({
6358
6458
  "data-iris-list-index": index,
6359
6459
  "data-iris-list-item": "",
6360
6460
  "data-state": selected ? "selected" : active ? "active" : "idle",
6461
+ "data-hovered": hoveredIndex.value === index ? "true" : "false",
6361
6462
  onClick: item.disabled ? void 0 : onClick,
6362
6463
  onFocus,
6464
+ onMouseenter: () => {
6465
+ hoveredIndex.value = index;
6466
+ },
6467
+ onMouseleave: () => {
6468
+ if (hoveredIndex.value === index) hoveredIndex.value = -1;
6469
+ },
6363
6470
  style: baseStyle
6364
6471
  },
6365
6472
  slotContent ?? item.label ?? String(item.value)
@@ -13497,6 +13604,7 @@ var IrisTreeSelect = vue.defineComponent({
13497
13604
  const { t } = useI18n();
13498
13605
  const open = vue.ref(false);
13499
13606
  const focused = vue.ref(false);
13607
+ const hoveredValue = vue.ref(null);
13500
13608
  const expanded = vue.ref(new Set(props.defaultExpanded));
13501
13609
  let rootEl = null;
13502
13610
  const selectNode = (node) => {
@@ -13534,6 +13642,12 @@ var IrisTreeSelect = vue.defineComponent({
13534
13642
  vue.h(
13535
13643
  "div",
13536
13644
  {
13645
+ onMouseenter: () => {
13646
+ hoveredValue.value = node.value;
13647
+ },
13648
+ onMouseleave: () => {
13649
+ if (hoveredValue.value === node.value) hoveredValue.value = null;
13650
+ },
13537
13651
  style: {
13538
13652
  display: "flex",
13539
13653
  alignItems: "center",
@@ -13542,7 +13656,7 @@ var IrisTreeSelect = vue.defineComponent({
13542
13656
  paddingInlineEnd: "6px",
13543
13657
  paddingBlock: "4px",
13544
13658
  borderRadius: "var(--iris-radius-sm, 4px)",
13545
- background: isSelected ? "var(--iris-surface-hover, rgba(99,102,241,0.1))" : "transparent"
13659
+ background: isSelected || hoveredValue.value === node.value ? "var(--iris-surface-hover, rgba(99,102,241,0.1))" : "transparent"
13546
13660
  }
13547
13661
  },
13548
13662
  [
@@ -13950,6 +14064,7 @@ var IrisCascader = vue.defineComponent({
13950
14064
  const open = vue.ref(false);
13951
14065
  const focused = vue.ref(false);
13952
14066
  const activePath = vue.ref([...props.modelValue]);
14067
+ const hoveredValue = vue.ref(null);
13953
14068
  let rootEl = null;
13954
14069
  const toggleOpen = () => {
13955
14070
  if (props.disabled) return;
@@ -14103,6 +14218,12 @@ var IrisCascader = vue.defineComponent({
14103
14218
  "data-iris-cascader-option": "",
14104
14219
  "data-value": node.value,
14105
14220
  onClick: () => selectOption(ci, node),
14221
+ onMouseenter: () => {
14222
+ hoveredValue.value = node.value;
14223
+ },
14224
+ onMouseleave: () => {
14225
+ if (hoveredValue.value === node.value) hoveredValue.value = null;
14226
+ },
14106
14227
  style: {
14107
14228
  display: "flex",
14108
14229
  alignItems: "center",
@@ -14113,7 +14234,7 @@ var IrisCascader = vue.defineComponent({
14113
14234
  borderRadius: "var(--iris-radius-sm, 4px)",
14114
14235
  cursor: node.disabled ? "not-allowed" : "pointer",
14115
14236
  color: node.disabled ? "var(--iris-muted)" : "var(--iris-foreground)",
14116
- background: isActive ? "var(--iris-surface-hover, rgba(99,102,241,0.1))" : "transparent"
14237
+ background: isActive || hoveredValue.value === node.value ? "var(--iris-surface-hover, rgba(99,102,241,0.1))" : "transparent"
14117
14238
  }
14118
14239
  },
14119
14240
  [