@1337exp/taoui 1.6.0 → 1.6.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.
package/dist/index.cjs CHANGED
@@ -109,7 +109,7 @@
109
109
  class: "tao-input__affix tao-input__affix--prefix"
110
110
  };
111
111
  const _hoisted_4$t = ["id", "type", "value", "placeholder", "disabled", "aria-invalid", "aria-describedby"];
112
- const _hoisted_5$m = {
112
+ const _hoisted_5$l = {
113
113
  key: 1,
114
114
  class: "tao-input__affix tao-input__affix--suffix"
115
115
  };
@@ -184,7 +184,7 @@
184
184
  onBlur: handleBlur,
185
185
  onFocus: handleFocus
186
186
  }, null, 42, _hoisted_4$t),
187
- _ctx.$slots.suffix ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_5$m, [
187
+ _ctx.$slots.suffix ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_5$l, [
188
188
  vue.renderSlot(_ctx.$slots, "suffix", {}, void 0, true)
189
189
  ])) : vue.createCommentVNode("", true)
190
190
  ], 2),
@@ -246,7 +246,7 @@
246
246
  };
247
247
  const _hoisted_3$x = ["aria-label", "disabled"];
248
248
  const _hoisted_4$s = { "aria-hidden": "true" };
249
- const _hoisted_5$l = ["aria-label", "disabled"];
249
+ const _hoisted_5$k = ["aria-label", "disabled"];
250
250
  const _hoisted_6$f = { "aria-hidden": "true" };
251
251
  const _sfc_main$R = /* @__PURE__ */ vue.defineComponent({
252
252
  ...{ name: "TaoInputNumber" },
@@ -428,7 +428,7 @@
428
428
  _cache[3] || (_cache[3] = vue.createTextVNode("−", -1))
429
429
  ], true)
430
430
  ])
431
- ], 8, _hoisted_5$l)
431
+ ], 8, _hoisted_5$k)
432
432
  ])) : vue.createCommentVNode("", true)
433
433
  ], 2);
434
434
  };
@@ -439,7 +439,7 @@
439
439
  const _hoisted_2$C = { "aria-hidden": "true" };
440
440
  const _hoisted_3$w = ["id", "value", "disabled", "aria-invalid", "aria-describedby", "aria-valuenow", "aria-valuemin", "aria-valuemax"];
441
441
  const _hoisted_4$r = ["aria-label", "disabled"];
442
- const _hoisted_5$k = { "aria-hidden": "true" };
442
+ const _hoisted_5$j = { "aria-hidden": "true" };
443
443
  const _sfc_main$Q = /* @__PURE__ */ vue.defineComponent({
444
444
  ...{ name: "TaoQuantity" },
445
445
  __name: "TaoQuantity",
@@ -610,7 +610,7 @@
610
610
  disabled: plusDisabled.value,
611
611
  onClick: onInc
612
612
  }, [
613
- vue.createElementVNode("span", _hoisted_5$k, [
613
+ vue.createElementVNode("span", _hoisted_5$j, [
614
614
  vue.renderSlot(_ctx.$slots, "increment-icon", {}, () => [
615
615
  _cache[1] || (_cache[1] = vue.createTextVNode("+", -1))
616
616
  ], true)
@@ -634,7 +634,7 @@
634
634
  key: 2,
635
635
  class: "tao-card__title-block"
636
636
  };
637
- const _hoisted_5$j = {
637
+ const _hoisted_5$i = {
638
638
  key: 0,
639
639
  class: "tao-card__title"
640
640
  };
@@ -704,7 +704,7 @@
704
704
  ])) : vue.createCommentVNode("", true)
705
705
  ], 2)) : vue.createCommentVNode("", true),
706
706
  _ctx.$slots.title || _ctx.$slots.sub ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$q, [
707
- _ctx.$slots.title ? (vue.openBlock(), vue.createElementBlock("h2", _hoisted_5$j, [
707
+ _ctx.$slots.title ? (vue.openBlock(), vue.createElementBlock("h2", _hoisted_5$i, [
708
708
  vue.renderSlot(_ctx.$slots, "title", {}, void 0, true)
709
709
  ])) : vue.createCommentVNode("", true),
710
710
  _ctx.$slots.sub ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6$e, [
@@ -751,6 +751,31 @@
751
751
  first.focus();
752
752
  }
753
753
  }
754
+ let locks = 0;
755
+ let previousOverflow = "";
756
+ function isBrowser() {
757
+ return typeof document !== "undefined";
758
+ }
759
+ function lockBodyScroll() {
760
+ if (!isBrowser()) {
761
+ return;
762
+ }
763
+ if (locks === 0) {
764
+ previousOverflow = document.body.style.overflow;
765
+ document.body.style.overflow = "hidden";
766
+ }
767
+ locks += 1;
768
+ }
769
+ function unlockBodyScroll() {
770
+ if (!isBrowser() || locks === 0) {
771
+ return;
772
+ }
773
+ locks -= 1;
774
+ if (locks === 0) {
775
+ document.body.style.overflow = previousOverflow;
776
+ previousOverflow = "";
777
+ }
778
+ }
754
779
  const _hoisted_1$H = ["aria-labelledby"];
755
780
  const _hoisted_2$A = {
756
781
  key: 0,
@@ -758,7 +783,7 @@
758
783
  };
759
784
  const _hoisted_3$u = ["id"];
760
785
  const _hoisted_4$p = { key: 1 };
761
- const _hoisted_5$i = ["aria-label"];
786
+ const _hoisted_5$h = ["aria-label"];
762
787
  const _hoisted_6$d = { "aria-hidden": "true" };
763
788
  const _hoisted_7$b = { class: "tao-modal__content" };
764
789
  const _hoisted_8$a = {
@@ -780,9 +805,8 @@
780
805
  const emit = __emit;
781
806
  const panelRef = vue.ref(null);
782
807
  const titleId = vue.useId();
783
- let previousOverflow = "";
784
808
  let previousFocus = null;
785
- let scrollLocked = false;
809
+ let scrollHeld = false;
786
810
  function close() {
787
811
  if (!props.closable) {
788
812
  return;
@@ -790,21 +814,19 @@
790
814
  emit("update:modelValue", false);
791
815
  emit("close");
792
816
  }
793
- function lockBodyScroll() {
794
- if (scrollLocked) {
817
+ function holdScroll() {
818
+ if (scrollHeld || !isBrowser()) {
795
819
  return;
796
820
  }
797
- previousOverflow = document.body.style.overflow;
798
- document.body.style.overflow = "hidden";
799
- scrollLocked = true;
821
+ lockBodyScroll();
822
+ scrollHeld = true;
800
823
  }
801
- function unlockBodyScroll() {
802
- if (!scrollLocked) {
824
+ function releaseScroll() {
825
+ if (!scrollHeld) {
803
826
  return;
804
827
  }
805
- document.body.style.overflow = previousOverflow;
806
- previousOverflow = "";
807
- scrollLocked = false;
828
+ unlockBodyScroll();
829
+ scrollHeld = false;
808
830
  }
809
831
  function restoreFocus() {
810
832
  var _a;
@@ -822,6 +844,9 @@
822
844
  }
823
845
  function onKeydown(event) {
824
846
  if (event.key === "Escape") {
847
+ if (!props.closable) {
848
+ return;
849
+ }
825
850
  event.preventDefault();
826
851
  close();
827
852
  return;
@@ -833,19 +858,23 @@
833
858
  vue.watch(
834
859
  () => props.modelValue,
835
860
  (isOpen) => {
861
+ if (!isBrowser()) {
862
+ return;
863
+ }
836
864
  if (isOpen) {
837
865
  previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
838
- lockBodyScroll();
866
+ holdScroll();
839
867
  void focusPanel();
840
868
  return;
841
869
  }
842
- unlockBodyScroll();
870
+ releaseScroll();
843
871
  restoreFocus();
844
872
  },
845
873
  { immediate: true }
846
874
  );
847
875
  vue.onBeforeUnmount(() => {
848
- unlockBodyScroll();
876
+ releaseScroll();
877
+ restoreFocus();
849
878
  });
850
879
  return (_ctx, _cache) => {
851
880
  return vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
@@ -886,7 +915,7 @@
886
915
  _cache[0] || (_cache[0] = vue.createTextVNode("×", -1))
887
916
  ], true)
888
917
  ])
889
- ], 8, _hoisted_5$i)) : vue.createCommentVNode("", true)
918
+ ], 8, _hoisted_5$h)) : vue.createCommentVNode("", true)
890
919
  ])) : vue.createCommentVNode("", true),
891
920
  vue.createElementVNode("div", _hoisted_7$b, [
892
921
  vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
@@ -903,7 +932,7 @@
903
932
  };
904
933
  }
905
934
  });
906
- const TaoModal = /* @__PURE__ */ _export_sfc(_sfc_main$O, [["__scopeId", "data-v-67d4b1e8"]]);
935
+ const TaoModal = /* @__PURE__ */ _export_sfc(_sfc_main$O, [["__scopeId", "data-v-102cfd66"]]);
907
936
  const _hoisted_1$G = { class: "tao-tabs" };
908
937
  const _hoisted_2$z = ["id", "aria-selected", "aria-controls", "tabindex", "disabled", "onClick"];
909
938
  const _hoisted_3$t = ["id", "aria-labelledby"];
@@ -1225,15 +1254,26 @@
1225
1254
  function close() {
1226
1255
  void applyOpen(false);
1227
1256
  }
1228
- async function applyOpen(next) {
1229
- var _a;
1230
- setOpen(next);
1231
- if (!next) {
1257
+ function bindDismiss() {
1258
+ if (typeof document === "undefined") {
1232
1259
  return;
1233
1260
  }
1234
- await vue.nextTick();
1235
- updatePosition();
1236
- (_a = panelRef.value) == null ? void 0 : _a.focus();
1261
+ document.addEventListener("pointerdown", onDocumentPointer);
1262
+ document.addEventListener("keydown", onDocumentKey);
1263
+ window.addEventListener("resize", onViewportChange);
1264
+ window.addEventListener("scroll", onViewportChange, true);
1265
+ }
1266
+ function unbindDismiss() {
1267
+ if (typeof document === "undefined") {
1268
+ return;
1269
+ }
1270
+ document.removeEventListener("pointerdown", onDocumentPointer);
1271
+ document.removeEventListener("keydown", onDocumentKey);
1272
+ window.removeEventListener("resize", onViewportChange);
1273
+ window.removeEventListener("scroll", onViewportChange, true);
1274
+ }
1275
+ function applyOpen(next) {
1276
+ setOpen(next);
1237
1277
  }
1238
1278
  function focusTrigger() {
1239
1279
  var _a, _b;
@@ -1246,7 +1286,7 @@
1246
1286
  function updatePosition() {
1247
1287
  const trigger = triggerRef.value;
1248
1288
  const panel = panelRef.value;
1249
- if (!trigger || !panel) {
1289
+ if (typeof window === "undefined" || !trigger || !panel) {
1250
1290
  return;
1251
1291
  }
1252
1292
  const rect = trigger.getBoundingClientRect();
@@ -1329,24 +1369,24 @@
1329
1369
  updatePosition();
1330
1370
  }
1331
1371
  }
1332
- vue.watch(open, (isOpen) => {
1333
- if (isOpen) {
1334
- document.addEventListener("pointerdown", onDocumentPointer);
1335
- document.addEventListener("keydown", onDocumentKey);
1336
- window.addEventListener("resize", onViewportChange);
1337
- window.addEventListener("scroll", onViewportChange, true);
1338
- return;
1339
- }
1340
- document.removeEventListener("pointerdown", onDocumentPointer);
1341
- document.removeEventListener("keydown", onDocumentKey);
1342
- window.removeEventListener("resize", onViewportChange);
1343
- window.removeEventListener("scroll", onViewportChange, true);
1344
- });
1372
+ vue.watch(
1373
+ open,
1374
+ (isOpen) => {
1375
+ if (isOpen) {
1376
+ bindDismiss();
1377
+ void vue.nextTick(() => {
1378
+ var _a;
1379
+ updatePosition();
1380
+ (_a = panelRef.value) == null ? void 0 : _a.focus();
1381
+ });
1382
+ return;
1383
+ }
1384
+ unbindDismiss();
1385
+ },
1386
+ { immediate: true }
1387
+ );
1345
1388
  vue.onBeforeUnmount(() => {
1346
- document.removeEventListener("pointerdown", onDocumentPointer);
1347
- document.removeEventListener("keydown", onDocumentKey);
1348
- window.removeEventListener("resize", onViewportChange);
1349
- window.removeEventListener("scroll", onViewportChange, true);
1389
+ unbindDismiss();
1350
1390
  });
1351
1391
  return (_ctx, _cache) => {
1352
1392
  return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$F, [
@@ -1378,7 +1418,7 @@
1378
1418
  };
1379
1419
  }
1380
1420
  });
1381
- const TaoPopover = /* @__PURE__ */ _export_sfc(_sfc_main$L, [["__scopeId", "data-v-e4ead301"]]);
1421
+ const TaoPopover = /* @__PURE__ */ _export_sfc(_sfc_main$L, [["__scopeId", "data-v-afd791a7"]]);
1382
1422
  const spoilerGroupKey = Symbol("taoSpoilerGroup");
1383
1423
  const _hoisted_1$E = { class: "tao-spoiler" };
1384
1424
  const _hoisted_2$y = ["aria-expanded", "aria-controls"];
@@ -1387,7 +1427,7 @@
1387
1427
  class: "tao-spoiler__title"
1388
1428
  };
1389
1429
  const _hoisted_4$o = ["id"];
1390
- const _hoisted_5$h = { class: "tao-spoiler__content-inner" };
1430
+ const _hoisted_5$g = { class: "tao-spoiler__content-inner" };
1391
1431
  const _sfc_main$K = /* @__PURE__ */ vue.defineComponent({
1392
1432
  ...{ name: "TaoSpoiler" },
1393
1433
  __name: "TaoSpoiler",
@@ -1473,7 +1513,7 @@
1473
1513
  id: vue.unref(panelId),
1474
1514
  class: "tao-spoiler__content"
1475
1515
  }, [
1476
- vue.createElementVNode("div", _hoisted_5$h, [
1516
+ vue.createElementVNode("div", _hoisted_5$g, [
1477
1517
  vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
1478
1518
  ])
1479
1519
  ], 8, _hoisted_4$o)) : vue.createCommentVNode("", true)
@@ -1490,14 +1530,19 @@
1490
1530
  ...{ name: "TaoSpoilerGroup" },
1491
1531
  __name: "TaoSpoilerGroup",
1492
1532
  props: {
1493
- modelValue: { default: null }
1533
+ modelValue: {}
1494
1534
  },
1495
1535
  emits: ["update:modelValue", "change"],
1496
1536
  setup(__props, { emit: __emit }) {
1497
1537
  const props = __props;
1498
1538
  const emit = __emit;
1499
- const model = vue.computed(() => props.modelValue);
1539
+ const isControlled = vue.computed(() => props.modelValue !== void 0);
1540
+ const internal = vue.ref(null);
1541
+ const model = vue.computed(() => isControlled.value ? props.modelValue : internal.value);
1500
1542
  function setOpen(name) {
1543
+ if (!isControlled.value) {
1544
+ internal.value = name;
1545
+ }
1501
1546
  emit("update:modelValue", name);
1502
1547
  emit("change", name);
1503
1548
  }
@@ -1512,7 +1557,7 @@
1512
1557
  };
1513
1558
  }
1514
1559
  });
1515
- const TaoSpoilerGroup = /* @__PURE__ */ _export_sfc(_sfc_main$J, [["__scopeId", "data-v-6b172e89"]]);
1560
+ const TaoSpoilerGroup = /* @__PURE__ */ _export_sfc(_sfc_main$J, [["__scopeId", "data-v-118970dd"]]);
1516
1561
  const _hoisted_1$C = ["aria-label"];
1517
1562
  const _sfc_main$I = /* @__PURE__ */ vue.defineComponent({
1518
1563
  ...{ name: "TaoCopy" },
@@ -2169,20 +2214,24 @@
2169
2214
  const props = __props;
2170
2215
  const emit = __emit;
2171
2216
  const isLoaded = vue.ref(false);
2217
+ const hasError = vue.ref(false);
2172
2218
  function handleLoad() {
2173
2219
  isLoaded.value = true;
2220
+ hasError.value = false;
2174
2221
  emit("load");
2175
2222
  }
2176
2223
  function handleError() {
2177
2224
  isLoaded.value = false;
2225
+ hasError.value = true;
2178
2226
  emit("error");
2179
2227
  }
2180
2228
  vue.watch(() => props.src, () => {
2181
2229
  isLoaded.value = false;
2230
+ hasError.value = false;
2182
2231
  });
2183
2232
  return (_ctx, _cache) => {
2184
2233
  return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$z, [
2185
- __props.src ? (vue.openBlock(), vue.createElementBlock("img", {
2234
+ __props.src && !hasError.value ? (vue.openBlock(), vue.createElementBlock("img", {
2186
2235
  key: 0,
2187
2236
  class: vue.normalizeClass({ "tao-image__img--hidden": !isLoaded.value, "tao-image__img--pixelated": props.pixelated }),
2188
2237
  src: __props.src,
@@ -2192,14 +2241,15 @@
2192
2241
  draggable: "false",
2193
2242
  onLoad: handleLoad,
2194
2243
  onError: handleError
2195
- }, null, 42, _hoisted_2$w)) : vue.renderSlot(_ctx.$slots, "default", {}, () => [
2244
+ }, null, 42, _hoisted_2$w)) : vue.createCommentVNode("", true),
2245
+ !__props.src || hasError.value ? vue.renderSlot(_ctx.$slots, "default", {}, () => [
2196
2246
  vue.createElementVNode("div", _hoisted_3$q, vue.toDisplayString(__props.placeholderText), 1)
2197
- ], true, 1)
2247
+ ], true, 1) : vue.createCommentVNode("", true)
2198
2248
  ]);
2199
2249
  };
2200
2250
  }
2201
2251
  });
2202
- const TaoImage = /* @__PURE__ */ _export_sfc(_sfc_main$B, [["__scopeId", "data-v-e7c911e5"]]);
2252
+ const TaoImage = /* @__PURE__ */ _export_sfc(_sfc_main$B, [["__scopeId", "data-v-aea39025"]]);
2203
2253
  const _hoisted_1$y = ["for"];
2204
2254
  const _hoisted_2$v = ["id", "checked", "disabled", "aria-checked", "aria-invalid", "aria-describedby"];
2205
2255
  const _hoisted_3$p = {
@@ -2737,7 +2787,7 @@
2737
2787
  key: 0,
2738
2788
  class: "tao-progress__percentage"
2739
2789
  };
2740
- const _hoisted_5$g = {
2790
+ const _hoisted_5$f = {
2741
2791
  key: 1,
2742
2792
  class: "tao-progress__side"
2743
2793
  };
@@ -2796,7 +2846,7 @@
2796
2846
  }, null, 6)
2797
2847
  ], 4)
2798
2848
  ]),
2799
- _ctx.$slots.right || showEndPercent.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$g, [
2849
+ _ctx.$slots.right || showEndPercent.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$f, [
2800
2850
  vue.renderSlot(_ctx.$slots, "right", {}, void 0, true),
2801
2851
  showEndPercent.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_6$c, vue.toDisplayString(endPercentLabel.value), 1)) : vue.createCommentVNode("", true)
2802
2852
  ])) : vue.createCommentVNode("", true)
@@ -3045,7 +3095,7 @@
3045
3095
  const _hoisted_2$n = { class: "tao-file-drop__row" };
3046
3096
  const _hoisted_3$j = ["aria-label"];
3047
3097
  const _hoisted_4$i = { "aria-hidden": "true" };
3048
- const _hoisted_5$f = ["accept", "multiple"];
3098
+ const _hoisted_5$e = ["accept", "multiple"];
3049
3099
  const _hoisted_6$b = {
3050
3100
  key: 0,
3051
3101
  class: "tao-file-drop__list"
@@ -3077,6 +3127,28 @@
3077
3127
  function sameFile(a, b) {
3078
3128
  return a.name === b.name && a.size === b.size && a.lastModified === b.lastModified;
3079
3129
  }
3130
+ function acceptTokens(accept) {
3131
+ return accept.split(",").map((token) => token.trim().toLowerCase()).filter(Boolean);
3132
+ }
3133
+ function fileMatchesAccept(file, accept) {
3134
+ const tokens = acceptTokens(accept);
3135
+ if (!tokens.length || tokens.includes("*") || tokens.includes("*/*")) {
3136
+ return true;
3137
+ }
3138
+ const name = file.name.toLowerCase();
3139
+ const mime = (file.type || "").toLowerCase();
3140
+ const dot = name.lastIndexOf(".");
3141
+ const ext = dot >= 0 ? name.slice(dot) : "";
3142
+ return tokens.some((token) => {
3143
+ if (token.startsWith(".")) {
3144
+ return ext === token;
3145
+ }
3146
+ if (token.endsWith("/*")) {
3147
+ return mime.startsWith(token.slice(0, -1));
3148
+ }
3149
+ return mime === token;
3150
+ });
3151
+ }
3080
3152
  function commit(files) {
3081
3153
  emit("update:modelValue", files);
3082
3154
  emit("files", files);
@@ -3109,9 +3181,17 @@
3109
3181
  function removeAt(index) {
3110
3182
  commit(props.modelValue.filter((_, item) => item !== index));
3111
3183
  }
3184
+ function resetInput() {
3185
+ const el = fileInput.value;
3186
+ if (el) {
3187
+ el.type = "text";
3188
+ el.type = "file";
3189
+ }
3190
+ }
3112
3191
  function processFiles(fileList) {
3113
- const incoming = Array.from(fileList);
3192
+ const incoming = Array.from(fileList).filter((file) => fileMatchesAccept(file, props.accept));
3114
3193
  if (!incoming.length) {
3194
+ resetInput();
3115
3195
  return;
3116
3196
  }
3117
3197
  let result;
@@ -3126,11 +3206,7 @@
3126
3206
  }
3127
3207
  }
3128
3208
  commit(result);
3129
- const el = fileInput.value;
3130
- if (el) {
3131
- el.type = "text";
3132
- el.type = "file";
3133
- }
3209
+ resetInput();
3134
3210
  }
3135
3211
  function defaultFormatSize(bytes) {
3136
3212
  if (bytes < 1024) {
@@ -3193,7 +3269,7 @@
3193
3269
  onChange: handleFileSelect,
3194
3270
  onClick: _cache[0] || (_cache[0] = vue.withModifiers(() => {
3195
3271
  }, ["stop"]))
3196
- }, null, 40, _hoisted_5$f)
3272
+ }, null, 40, _hoisted_5$e)
3197
3273
  ], 34)
3198
3274
  ]),
3199
3275
  __props.list && __props.modelValue.length ? (vue.openBlock(), vue.createElementBlock("ul", _hoisted_6$b, [
@@ -3223,12 +3299,14 @@
3223
3299
  };
3224
3300
  }
3225
3301
  });
3226
- const TaoFileDrop = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["__scopeId", "data-v-570fc1bb"]]);
3227
- const _hoisted_1$p = ["aria-expanded"];
3228
- const _hoisted_2$m = ["aria-label"];
3229
- const _hoisted_3$i = { "aria-hidden": "true" };
3230
- const _hoisted_4$h = ["onClick", "onMouseenter"];
3231
- const _hoisted_5$e = { key: 1 };
3302
+ const TaoFileDrop = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["__scopeId", "data-v-4b36e2a3"]]);
3303
+ const _hoisted_1$p = ["aria-expanded", "aria-label"];
3304
+ const _hoisted_2$m = {
3305
+ key: 1,
3306
+ "aria-hidden": "true"
3307
+ };
3308
+ const _hoisted_3$i = ["onClick", "onMouseenter"];
3309
+ const _hoisted_4$h = { key: 1 };
3232
3310
  const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
3233
3311
  ...{ name: "TaoDropdownMenu" },
3234
3312
  __name: "TaoDropdownMenu",
@@ -3363,18 +3441,14 @@
3363
3441
  class: "tao-dropdown-menu__button",
3364
3442
  "aria-haspopup": "menu",
3365
3443
  "aria-expanded": isOpen.value,
3444
+ "aria-label": _ctx.$slots.button ? void 0 : __props.menuLabel,
3366
3445
  onClick: toggleMenu
3367
3446
  }, [
3368
- _ctx.$slots.button ? vue.renderSlot(_ctx.$slots, "button", {}, void 0, true, 0) : (vue.openBlock(), vue.createElementBlock("span", {
3369
- key: 1,
3370
- "aria-label": __props.menuLabel
3371
- }, [
3372
- vue.createElementVNode("span", _hoisted_3$i, [
3373
- vue.renderSlot(_ctx.$slots, "icon", {}, () => [
3374
- _cache[0] || (_cache[0] = vue.createTextVNode("⋮", -1))
3375
- ], true)
3376
- ])
3377
- ], 8, _hoisted_2$m))
3447
+ _ctx.$slots.button ? vue.renderSlot(_ctx.$slots, "button", {}, void 0, true, 0) : (vue.openBlock(), vue.createElementBlock("span", _hoisted_2$m, [
3448
+ vue.renderSlot(_ctx.$slots, "icon", {}, () => [
3449
+ _cache[0] || (_cache[0] = vue.createTextVNode("⋮", -1))
3450
+ ], true)
3451
+ ]))
3378
3452
  ], 8, _hoisted_1$p),
3379
3453
  (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
3380
3454
  isOpen.value ? (vue.openBlock(), vue.createElementBlock("div", {
@@ -3400,8 +3474,8 @@
3400
3474
  id: action.id,
3401
3475
  ico: action.ico,
3402
3476
  text: action.name
3403
- }, void 0, true, 0) : (vue.openBlock(), vue.createElementBlock("span", _hoisted_5$e, vue.toDisplayString(action.name), 1))
3404
- ], 42, _hoisted_4$h);
3477
+ }, void 0, true, 0) : (vue.openBlock(), vue.createElementBlock("span", _hoisted_4$h, vue.toDisplayString(action.name), 1))
3478
+ ], 42, _hoisted_3$i);
3405
3479
  }), 128))
3406
3480
  ], 36)) : vue.createCommentVNode("", true)
3407
3481
  ]))
@@ -3409,9 +3483,9 @@
3409
3483
  };
3410
3484
  }
3411
3485
  });
3412
- const TaoDropdownMenu = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["__scopeId", "data-v-42bc0a2a"]]);
3486
+ const TaoDropdownMenu = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["__scopeId", "data-v-4750fe54"]]);
3413
3487
  const _hoisted_1$o = ["aria-invalid", "aria-describedby"];
3414
- const _hoisted_2$l = ["id", "value", "placeholder", "type", "inputmode", "pattern", "onInput", "onKeydown", "onFocus"];
3488
+ const _hoisted_2$l = ["id", "value", "placeholder", "type", "inputmode", "pattern", "maxlength", "onInput", "onPaste", "onKeydown", "onFocus"];
3415
3489
  const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
3416
3490
  ...{ name: "TaoPinCode" },
3417
3491
  __name: "TaoPinCode",
@@ -3469,11 +3543,43 @@
3469
3543
  function isFilled() {
3470
3544
  return numbers.value.length === props.length && numbers.value.every((cell) => cell !== "");
3471
3545
  }
3546
+ function applyChars(index, raw) {
3547
+ var _a;
3548
+ const chars = [...raw].map((ch) => acceptChar(ch)).filter(Boolean);
3549
+ if (!chars.length) {
3550
+ return;
3551
+ }
3552
+ numbers.value = [...numbers.value];
3553
+ let cursor = index;
3554
+ for (const ch of chars) {
3555
+ if (cursor >= props.length) {
3556
+ break;
3557
+ }
3558
+ numbers.value[cursor] = ch;
3559
+ cursor += 1;
3560
+ }
3561
+ emitChange();
3562
+ if (isFilled()) {
3563
+ (_a = inputRefs.value[index]) == null ? void 0 : _a.blur();
3564
+ emit("complete", serialize());
3565
+ return;
3566
+ }
3567
+ if (cursor < props.length) {
3568
+ focusCell(cursor);
3569
+ }
3570
+ }
3472
3571
  function mutation(v, index) {
3473
3572
  var _a;
3474
- const char = v.length > 1 ? v[v.length - 1] ?? "" : v;
3475
- const next = acceptChar(char);
3476
- if (props.numbersOnly && char && !next) {
3573
+ if (v.length > 1) {
3574
+ applyChars(index, v);
3575
+ return;
3576
+ }
3577
+ const next = acceptChar(v);
3578
+ if (props.numbersOnly && v && !next) {
3579
+ const el = inputRefs.value[index];
3580
+ if (el) {
3581
+ el.value = numbers.value[index] ?? "";
3582
+ }
3477
3583
  return;
3478
3584
  }
3479
3585
  numbers.value = [...numbers.value];
@@ -3493,6 +3599,15 @@
3493
3599
  focusCell(target);
3494
3600
  }
3495
3601
  }
3602
+ function onPaste(event, index) {
3603
+ var _a;
3604
+ const text = ((_a = event.clipboardData) == null ? void 0 : _a.getData("text")) ?? "";
3605
+ if (!text) {
3606
+ return;
3607
+ }
3608
+ event.preventDefault();
3609
+ applyChars(index, text);
3610
+ }
3496
3611
  function onFocus(index) {
3497
3612
  if (props.clearOn === "input") {
3498
3613
  const firstEmpty = firstEmptyIndex();
@@ -3574,8 +3689,9 @@
3574
3689
  inputmode: __props.numbersOnly ? "numeric" : "text",
3575
3690
  pattern: __props.numbersOnly ? "[0-9]" : void 0,
3576
3691
  autocomplete: "one-time-code",
3577
- maxlength: "1",
3692
+ maxlength: index === 0 ? __props.length : 1,
3578
3693
  onInput: ($event) => onChange($event, index),
3694
+ onPaste: ($event) => onPaste($event, index),
3579
3695
  onKeydown: ($event) => onKeydown($event, index),
3580
3696
  onFocus: ($event) => onFocus(index),
3581
3697
  onBlur
@@ -3585,7 +3701,7 @@
3585
3701
  };
3586
3702
  }
3587
3703
  });
3588
- const TaoPinCode = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-c3182673"]]);
3704
+ const TaoPinCode = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-44474500"]]);
3589
3705
  const _sfc_main$o = /* @__PURE__ */ vue.defineComponent({
3590
3706
  ...{ name: "TaoLink" },
3591
3707
  __name: "TaoLink",
@@ -3642,6 +3758,7 @@
3642
3758
  const id = vue.useId();
3643
3759
  const hintId = `${id}-hint`;
3644
3760
  const errorId = `${id}-error`;
3761
+ const labelId = `${id}-label`;
3645
3762
  const invalid = vue.computed(() => Boolean(props.error));
3646
3763
  const describedBy = vue.computed(() => {
3647
3764
  if (props.error) {
@@ -3657,14 +3774,27 @@
3657
3774
  invalid,
3658
3775
  describedBy
3659
3776
  });
3777
+ function onLabelClick() {
3778
+ var _a, _b;
3779
+ const target = document.getElementById(id);
3780
+ if (target instanceof HTMLInputElement || target instanceof HTMLButtonElement || target instanceof HTMLSelectElement || target instanceof HTMLTextAreaElement) {
3781
+ return;
3782
+ }
3783
+ const scope = target ?? ((_a = document.getElementById(labelId)) == null ? void 0 : _a.parentElement);
3784
+ (_b = scope == null ? void 0 : scope.querySelector(
3785
+ "input:not([disabled]), button:not([disabled]), textarea:not([disabled]), select:not([disabled])"
3786
+ )) == null ? void 0 : _b.focus();
3787
+ }
3660
3788
  return (_ctx, _cache) => {
3661
3789
  return vue.openBlock(), vue.createElementBlock("div", {
3662
3790
  class: vue.normalizeClass(["tao-form-field", { "tao-form-field--invalid": invalid.value }])
3663
3791
  }, [
3664
3792
  __props.label ? (vue.openBlock(), vue.createElementBlock("label", {
3665
3793
  key: 0,
3794
+ id: labelId,
3666
3795
  class: "tao-form-field__label",
3667
- for: vue.unref(id)
3796
+ for: vue.unref(id),
3797
+ onClick: onLabelClick
3668
3798
  }, vue.toDisplayString(__props.label), 9, _hoisted_1$n)) : vue.createCommentVNode("", true),
3669
3799
  vue.renderSlot(_ctx.$slots, "default", {}, void 0, true),
3670
3800
  __props.error ? (vue.openBlock(), vue.createElementBlock("p", {
@@ -3680,7 +3810,7 @@
3680
3810
  };
3681
3811
  }
3682
3812
  });
3683
- const TaoFormField = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["__scopeId", "data-v-11324f0c"]]);
3813
+ const TaoFormField = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["__scopeId", "data-v-edd0be31"]]);
3684
3814
  const _hoisted_1$m = ["id", "aria-expanded", "aria-invalid", "aria-describedby", "disabled"];
3685
3815
  const _hoisted_2$k = { class: "tao-select__value" };
3686
3816
  const _hoisted_3$h = ["aria-activedescendant"];
@@ -3724,12 +3854,16 @@
3724
3854
  }
3725
3855
  const rect = trigger.getBoundingClientRect();
3726
3856
  const panelHeight = panel.offsetHeight;
3857
+ const panelWidth = panel.offsetWidth || rect.width;
3727
3858
  const gap = 4;
3859
+ const pad = 8;
3728
3860
  const spaceBelow = window.innerHeight - rect.bottom - gap;
3729
3861
  const openUp = spaceBelow < panelHeight && rect.top > spaceBelow;
3862
+ const maxLeft = Math.max(pad, window.innerWidth - panelWidth - pad);
3863
+ const left = Math.min(Math.max(rect.left, pad), maxLeft);
3730
3864
  listStyle.value = {
3731
3865
  top: `${openUp ? rect.top - panelHeight - gap : rect.bottom + gap}px`,
3732
- left: `${rect.left}px`,
3866
+ left: `${left}px`,
3733
3867
  width: `${rect.width}px`
3734
3868
  };
3735
3869
  }
@@ -3743,7 +3877,7 @@
3743
3877
  return;
3744
3878
  }
3745
3879
  const selectedIndex = props.options.findIndex((option) => option.value === props.modelValue);
3746
- activeIndex.value = selectedIndex >= 0 ? selectedIndex : enabledIndexes.value[0] ?? -1;
3880
+ activeIndex.value = selectedIndex >= 0 && enabledIndexes.value.includes(selectedIndex) ? selectedIndex : enabledIndexes.value[0] ?? -1;
3747
3881
  await vue.nextTick();
3748
3882
  updatePosition();
3749
3883
  (_a = listRef.value) == null ? void 0 : _a.focus();
@@ -3963,7 +4097,7 @@
3963
4097
  };
3964
4098
  }
3965
4099
  });
3966
- const TaoSelect = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["__scopeId", "data-v-c5d6cdd3"]]);
4100
+ const TaoSelect = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["__scopeId", "data-v-d9b336d8"]]);
3967
4101
  const _hoisted_1$l = ["id", "aria-expanded", "aria-activedescendant", "aria-invalid", "aria-describedby", "disabled", "placeholder", "value"];
3968
4102
  const _hoisted_2$j = {
3969
4103
  key: 0,
@@ -4051,12 +4185,16 @@
4051
4185
  }
4052
4186
  const rect = trigger.getBoundingClientRect();
4053
4187
  const panelHeight = panel.offsetHeight;
4188
+ const panelWidth = panel.offsetWidth || rect.width;
4054
4189
  const gap = 4;
4190
+ const pad = 8;
4055
4191
  const spaceBelow = window.innerHeight - rect.bottom - gap;
4056
4192
  const openUp = spaceBelow < panelHeight && rect.top > spaceBelow;
4193
+ const maxLeft = Math.max(pad, window.innerWidth - panelWidth - pad);
4194
+ const left = Math.min(Math.max(rect.left, pad), maxLeft);
4057
4195
  listStyle.value = {
4058
4196
  top: `${openUp ? rect.top - panelHeight - gap : rect.bottom + gap}px`,
4059
- left: `${rect.left}px`,
4197
+ left: `${left}px`,
4060
4198
  width: `${rect.width}px`
4061
4199
  };
4062
4200
  }
@@ -4123,6 +4261,13 @@
4123
4261
  }
4124
4262
  commitCreated(value);
4125
4263
  }
4264
+ function clear() {
4265
+ var _a;
4266
+ emitValue(null);
4267
+ query.value = "";
4268
+ open.value = false;
4269
+ (_a = inputRef.value) == null ? void 0 : _a.focus();
4270
+ }
4126
4271
  function revertQuery() {
4127
4272
  syncQueryFromModel();
4128
4273
  }
@@ -4440,7 +4585,8 @@
4440
4585
  key: 0,
4441
4586
  type: "button",
4442
4587
  class: "tao-combobox__clear",
4443
- onMousedown: vue.withModifiers(markPicking, ["prevent"])
4588
+ onMousedown: vue.withModifiers(markPicking, ["prevent"]),
4589
+ onClick: clear
4444
4590
  }, [
4445
4591
  vue.renderSlot(_ctx.$slots, "clear", {}, () => [
4446
4592
  vue.createTextVNode(vue.toDisplayString(__props.clearText), 1)
@@ -4452,7 +4598,7 @@
4452
4598
  };
4453
4599
  }
4454
4600
  });
4455
- const TaoCombobox = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["__scopeId", "data-v-2281e009"]]);
4601
+ const TaoCombobox = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["__scopeId", "data-v-131d254d"]]);
4456
4602
  const ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
4457
4603
  function formatTaoDateIso(parts) {
4458
4604
  return `${String(parts.y).padStart(4, "0")}-${String(parts.m).padStart(2, "0")}-${String(parts.d).padStart(2, "0")}`;
@@ -4491,8 +4637,23 @@
4491
4637
  if (!parts) {
4492
4638
  return iso;
4493
4639
  }
4494
- const date = new Date(parts.y, parts.m - 1 + months, parts.d);
4495
- return formatTaoDateIso({ y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate() });
4640
+ const monthStart = new Date(parts.y, parts.m - 1 + months, 1);
4641
+ const y = monthStart.getFullYear();
4642
+ const m = monthStart.getMonth() + 1;
4643
+ const lastDay = new Date(y, m, 0).getDate();
4644
+ return formatTaoDateIso({ y, m, d: Math.min(parts.d, lastDay) });
4645
+ }
4646
+ function clampTaoDateCursor(iso, min, max) {
4647
+ if (isTaoDateInRange(iso, min, max)) {
4648
+ return iso;
4649
+ }
4650
+ if (min && parseTaoDate(min) && iso < min) {
4651
+ return min;
4652
+ }
4653
+ if (max && parseTaoDate(max) && iso > max) {
4654
+ return max;
4655
+ }
4656
+ return iso;
4496
4657
  }
4497
4658
  function isTaoDateInRange(iso, min, max) {
4498
4659
  if (!parseTaoDate(iso)) {
@@ -4683,7 +4844,7 @@
4683
4844
  if (!next) {
4684
4845
  return;
4685
4846
  }
4686
- syncViewFrom(valueIso.value ?? todayIso.value);
4847
+ syncViewFrom(clampTaoDateCursor(valueIso.value ?? todayIso.value, props.min, props.max));
4687
4848
  await vue.nextTick();
4688
4849
  updatePosition();
4689
4850
  (_a = panelRef.value) == null ? void 0 : _a.focus();
@@ -4712,18 +4873,13 @@
4712
4873
  (_a = triggerRef.value) == null ? void 0 : _a.focus();
4713
4874
  }
4714
4875
  function goMonth(delta) {
4715
- const next = shiftTaoMonth(`${viewYear.value}-${String(viewMonth.value).padStart(2, "0")}-01`, delta);
4716
- const parts = parseTaoDate(next);
4717
- if (!parts) {
4718
- return;
4719
- }
4720
- viewYear.value = parts.y;
4721
- viewMonth.value = parts.m;
4722
- cursorIso.value = shiftTaoMonth(cursorIso.value, delta);
4876
+ cursorIso.value = clampTaoDateCursor(shiftTaoMonth(cursorIso.value, delta), props.min, props.max);
4877
+ syncViewFrom(cursorIso.value);
4723
4878
  void vue.nextTick(updatePosition);
4724
4879
  }
4725
4880
  function moveCursor(days) {
4726
- cursorIso.value = shiftTaoDate(cursorIso.value, days);
4881
+ const next = shiftTaoDate(cursorIso.value, days);
4882
+ cursorIso.value = isTaoDateInRange(next, props.min, props.max) ? next : clampTaoDateCursor(next, props.min, props.max);
4727
4883
  syncViewFrom(cursorIso.value);
4728
4884
  void vue.nextTick(updatePosition);
4729
4885
  }
@@ -4991,7 +5147,7 @@
4991
5147
  };
4992
5148
  }
4993
5149
  });
4994
- const TaoDate = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["__scopeId", "data-v-771836c8"]]);
5150
+ const TaoDate = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["__scopeId", "data-v-ebd437a8"]]);
4995
5151
  const _hoisted_1$j = ["id", "aria-expanded", "aria-invalid", "aria-describedby", "disabled"];
4996
5152
  const _hoisted_2$h = { class: "tao-date-range__value" };
4997
5153
  const _hoisted_3$e = {
@@ -5106,7 +5262,7 @@
5106
5262
  }
5107
5263
  draftStart.value = null;
5108
5264
  hoverIso.value = null;
5109
- syncViewFrom(((_a = committed.value) == null ? void 0 : _a.start) ?? todayIso.value);
5265
+ syncViewFrom(clampTaoDateCursor(((_a = committed.value) == null ? void 0 : _a.start) ?? todayIso.value, props.min, props.max));
5110
5266
  await vue.nextTick();
5111
5267
  updatePosition();
5112
5268
  (_b = panelRef.value) == null ? void 0 : _b.focus();
@@ -5155,19 +5311,14 @@
5155
5311
  }
5156
5312
  function goMonth(delta) {
5157
5313
  hoverIso.value = null;
5158
- const next = shiftTaoMonth(`${viewYear.value}-${String(viewMonth.value).padStart(2, "0")}-01`, delta);
5159
- const parts = parseTaoDate(next);
5160
- if (!parts) {
5161
- return;
5162
- }
5163
- viewYear.value = parts.y;
5164
- viewMonth.value = parts.m;
5165
- cursorIso.value = shiftTaoMonth(cursorIso.value, delta);
5314
+ cursorIso.value = clampTaoDateCursor(shiftTaoMonth(cursorIso.value, delta), props.min, props.max);
5315
+ syncViewFrom(cursorIso.value);
5166
5316
  void vue.nextTick(updatePosition);
5167
5317
  }
5168
5318
  function moveCursor(days) {
5169
5319
  hoverIso.value = null;
5170
- cursorIso.value = shiftTaoDate(cursorIso.value, days);
5320
+ const next = shiftTaoDate(cursorIso.value, days);
5321
+ cursorIso.value = isTaoDateInRange(next, props.min, props.max) ? next : clampTaoDateCursor(next, props.min, props.max);
5171
5322
  syncViewFrom(cursorIso.value);
5172
5323
  void vue.nextTick(updatePosition);
5173
5324
  }
@@ -5462,9 +5613,9 @@
5462
5613
  };
5463
5614
  }
5464
5615
  });
5465
- const TaoDateRange = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-4394053c"]]);
5616
+ const TaoDateRange = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-aa589793"]]);
5466
5617
  const _hoisted_1$i = ["for"];
5467
- const _hoisted_2$g = ["id", "checked", "disabled", "aria-checked"];
5618
+ const _hoisted_2$g = ["id", "checked", "disabled", "aria-checked", "aria-invalid", "aria-describedby"];
5468
5619
  const _hoisted_3$d = {
5469
5620
  key: 0,
5470
5621
  class: "tao-switch__label"
@@ -5488,6 +5639,8 @@
5488
5639
  const field = vue.inject(formFieldKey, null);
5489
5640
  const localId = vue.useId();
5490
5641
  const controlId = vue.computed(() => (field == null ? void 0 : field.id) ?? localId);
5642
+ const invalid = vue.computed(() => Boolean(field == null ? void 0 : field.invalid.value));
5643
+ const describedBy = vue.computed(() => field == null ? void 0 : field.describedBy.value);
5491
5644
  function toggle() {
5492
5645
  if (props.disabled) {
5493
5646
  return;
@@ -5498,7 +5651,7 @@
5498
5651
  }
5499
5652
  return (_ctx, _cache) => {
5500
5653
  return vue.openBlock(), vue.createElementBlock("label", {
5501
- class: vue.normalizeClass(["tao-switch", { "tao-switch--disabled": __props.disabled, "tao-switch--on": __props.modelValue }]),
5654
+ class: vue.normalizeClass(["tao-switch", { "tao-switch--disabled": __props.disabled, "tao-switch--on": __props.modelValue, "tao-switch--invalid": invalid.value }]),
5502
5655
  for: controlId.value
5503
5656
  }, [
5504
5657
  vue.createElementVNode("input", {
@@ -5509,6 +5662,8 @@
5509
5662
  checked: __props.modelValue,
5510
5663
  disabled: __props.disabled,
5511
5664
  "aria-checked": __props.modelValue,
5665
+ "aria-invalid": invalid.value || void 0,
5666
+ "aria-describedby": describedBy.value,
5512
5667
  onChange: toggle
5513
5668
  }, null, 40, _hoisted_2$g),
5514
5669
  _cache[0] || (_cache[0] = vue.createElementVNode("span", {
@@ -5524,10 +5679,10 @@
5524
5679
  };
5525
5680
  }
5526
5681
  });
5527
- const TaoSwitch = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["__scopeId", "data-v-db2bca61"]]);
5682
+ const TaoSwitch = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["__scopeId", "data-v-17ce5000"]]);
5528
5683
  const radioGroupKey = Symbol("taoRadioGroup");
5529
5684
  const _hoisted_1$h = ["for"];
5530
- const _hoisted_2$f = ["id", "name", "value", "checked", "disabled"];
5685
+ const _hoisted_2$f = ["id", "name", "value", "checked", "disabled", "aria-invalid", "aria-describedby"];
5531
5686
  const _hoisted_3$c = {
5532
5687
  key: 0,
5533
5688
  class: "tao-radio__label"
@@ -5551,7 +5706,11 @@
5551
5706
  const props = __props;
5552
5707
  const emit = __emit;
5553
5708
  const group = vue.inject(radioGroupKey, null);
5709
+ const field = vue.inject(formFieldKey, null);
5554
5710
  const localId = vue.useId();
5711
+ const controlId = vue.computed(() => group ? localId : (field == null ? void 0 : field.id) ?? localId);
5712
+ const invalid = vue.computed(() => Boolean(field == null ? void 0 : field.invalid.value));
5713
+ const describedBy = vue.computed(() => group ? void 0 : field == null ? void 0 : field.describedBy.value);
5555
5714
  const isDisabled = vue.computed(() => props.disabled || Boolean(group == null ? void 0 : group.disabled.value));
5556
5715
  const inputName = vue.computed(() => (group == null ? void 0 : group.name.value) ?? props.name);
5557
5716
  const isChecked = vue.computed(() => {
@@ -5571,17 +5730,19 @@
5571
5730
  }
5572
5731
  return (_ctx, _cache) => {
5573
5732
  return vue.openBlock(), vue.createElementBlock("label", {
5574
- class: vue.normalizeClass(["tao-radio", { "tao-radio--disabled": isDisabled.value }]),
5575
- for: vue.unref(localId)
5733
+ class: vue.normalizeClass(["tao-radio", { "tao-radio--disabled": isDisabled.value, "tao-radio--invalid": invalid.value && !vue.unref(group) }]),
5734
+ for: controlId.value
5576
5735
  }, [
5577
5736
  vue.createElementVNode("input", {
5578
- id: vue.unref(localId),
5737
+ id: controlId.value,
5579
5738
  class: "tao-radio__input",
5580
5739
  type: "radio",
5581
5740
  name: inputName.value,
5582
5741
  value: String(__props.value),
5583
5742
  checked: isChecked.value,
5584
5743
  disabled: isDisabled.value,
5744
+ "aria-invalid": !vue.unref(group) && invalid.value || void 0,
5745
+ "aria-describedby": describedBy.value,
5585
5746
  onChange
5586
5747
  }, null, 40, _hoisted_2$f),
5587
5748
  _cache[0] || (_cache[0] = vue.createElementVNode("span", {
@@ -5595,8 +5756,8 @@
5595
5756
  };
5596
5757
  }
5597
5758
  });
5598
- const TaoRadio = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["__scopeId", "data-v-c9c84481"]]);
5599
- const _hoisted_1$g = ["disabled"];
5759
+ const TaoRadio = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["__scopeId", "data-v-e79d1fb6"]]);
5760
+ const _hoisted_1$g = ["id", "disabled", "aria-describedby", "aria-invalid", "aria-labelledby"];
5600
5761
  const _hoisted_2$e = {
5601
5762
  key: 0,
5602
5763
  class: "tao-radio-group__legend"
@@ -5615,10 +5776,14 @@
5615
5776
  setup(__props, { emit: __emit }) {
5616
5777
  const props = __props;
5617
5778
  const emit = __emit;
5779
+ const field = vue.inject(formFieldKey, null);
5618
5780
  const autoName = vue.useId();
5619
5781
  const groupName = vue.computed(() => props.name || autoName);
5620
5782
  const model = vue.computed(() => props.modelValue);
5621
5783
  const groupDisabled = vue.computed(() => props.disabled);
5784
+ const invalid = vue.computed(() => Boolean(field == null ? void 0 : field.invalid.value));
5785
+ const describedBy = vue.computed(() => field == null ? void 0 : field.describedBy.value);
5786
+ const labelledBy = vue.computed(() => props.legend || !field ? void 0 : `${field.id}-label`);
5622
5787
  function setValue(value) {
5623
5788
  emit("update:modelValue", value);
5624
5789
  emit("change", value);
@@ -5630,9 +5795,14 @@
5630
5795
  setValue
5631
5796
  });
5632
5797
  return (_ctx, _cache) => {
5798
+ var _a;
5633
5799
  return vue.openBlock(), vue.createElementBlock("fieldset", {
5634
- class: vue.normalizeClass(["tao-radio-group", `tao-radio-group--${__props.direction}`]),
5635
- disabled: __props.disabled
5800
+ id: (_a = vue.unref(field)) == null ? void 0 : _a.id,
5801
+ class: vue.normalizeClass(["tao-radio-group", [`tao-radio-group--${__props.direction}`, { "tao-radio-group--invalid": invalid.value }]]),
5802
+ disabled: __props.disabled,
5803
+ "aria-describedby": describedBy.value,
5804
+ "aria-invalid": invalid.value || void 0,
5805
+ "aria-labelledby": labelledBy.value
5636
5806
  }, [
5637
5807
  __props.legend ? (vue.openBlock(), vue.createElementBlock("legend", _hoisted_2$e, vue.toDisplayString(__props.legend), 1)) : vue.createCommentVNode("", true),
5638
5808
  vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
@@ -5640,9 +5810,9 @@
5640
5810
  };
5641
5811
  }
5642
5812
  });
5643
- const TaoRadioGroup = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["__scopeId", "data-v-a0b1cb1f"]]);
5813
+ const TaoRadioGroup = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["__scopeId", "data-v-6f6fa977"]]);
5644
5814
  const segmentedKey = Symbol("taoSegmented");
5645
- const _hoisted_1$f = ["disabled", "aria-describedby", "aria-invalid"];
5815
+ const _hoisted_1$f = ["disabled", "aria-describedby", "aria-invalid", "aria-labelledby", "id"];
5646
5816
  const _hoisted_2$d = {
5647
5817
  key: 0,
5648
5818
  class: "tao-segmented__legend"
@@ -5742,6 +5912,7 @@
5742
5912
  mutationObserver = null;
5743
5913
  });
5744
5914
  return (_ctx, _cache) => {
5915
+ var _a;
5745
5916
  return vue.openBlock(), vue.createElementBlock("fieldset", {
5746
5917
  class: vue.normalizeClass(["tao-segmented", [
5747
5918
  `tao-segmented--${__props.size}`,
@@ -5753,7 +5924,9 @@
5753
5924
  ]]),
5754
5925
  disabled: __props.disabled,
5755
5926
  "aria-describedby": describedBy.value,
5756
- "aria-invalid": invalid.value || void 0
5927
+ "aria-invalid": invalid.value || void 0,
5928
+ "aria-labelledby": __props.legend ? void 0 : vue.unref(field) ? `${vue.unref(field).id}-label` : void 0,
5929
+ id: (_a = vue.unref(field)) == null ? void 0 : _a.id
5757
5930
  }, [
5758
5931
  __props.legend ? (vue.openBlock(), vue.createElementBlock("legend", _hoisted_2$d, vue.toDisplayString(__props.legend), 1)) : vue.createCommentVNode("", true),
5759
5932
  vue.createElementVNode("div", {
@@ -5772,7 +5945,7 @@
5772
5945
  };
5773
5946
  }
5774
5947
  });
5775
- const TaoSegmented = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["__scopeId", "data-v-cb3c591b"]]);
5948
+ const TaoSegmented = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["__scopeId", "data-v-af757a32"]]);
5776
5949
  const _hoisted_1$e = ["for"];
5777
5950
  const _hoisted_2$c = ["id", "name", "value", "checked", "disabled", "aria-label"];
5778
5951
  const _hoisted_3$b = { class: "tao-segmented-option__face" };
@@ -6186,11 +6359,15 @@
6186
6359
  const items = vue.computed(() => buildPaginationItems(current.value, pageCount.value, props.siblingCount));
6187
6360
  const from = vue.computed(() => props.total === 0 ? 0 : (current.value - 1) * props.pageSize + 1);
6188
6361
  const to = vue.computed(() => Math.min(current.value * props.pageSize, props.total));
6189
- vue.watch(pageCount, (count) => {
6190
- if (props.page > count) {
6191
- goTo(count);
6192
- }
6193
- });
6362
+ vue.watch(
6363
+ () => [props.page, pageCount.value],
6364
+ ([page, count]) => {
6365
+ if (page > count || page < 1) {
6366
+ goTo(page);
6367
+ }
6368
+ },
6369
+ { immediate: true }
6370
+ );
6194
6371
  function goTo(next) {
6195
6372
  if (props.disabled) {
6196
6373
  return;
@@ -6274,7 +6451,7 @@
6274
6451
  };
6275
6452
  }
6276
6453
  });
6277
- const TaoPagination = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-a890810c"]]);
6454
+ const TaoPagination = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-37f3d381"]]);
6278
6455
  const _hoisted_1$a = { class: "tao-empty" };
6279
6456
  const _hoisted_2$8 = {
6280
6457
  key: 0,
@@ -6376,9 +6553,8 @@
6376
6553
  const emit = __emit;
6377
6554
  const panelRef = vue.ref(null);
6378
6555
  const titleId = vue.useId();
6379
- let previousOverflow = "";
6380
6556
  let previousFocus = null;
6381
- let scrollLocked = false;
6557
+ let scrollHeld = false;
6382
6558
  function close() {
6383
6559
  if (!props.closable) {
6384
6560
  return;
@@ -6386,21 +6562,19 @@
6386
6562
  emit("update:modelValue", false);
6387
6563
  emit("close");
6388
6564
  }
6389
- function lockBodyScroll() {
6390
- if (scrollLocked) {
6565
+ function holdScroll() {
6566
+ if (scrollHeld || !isBrowser()) {
6391
6567
  return;
6392
6568
  }
6393
- previousOverflow = document.body.style.overflow;
6394
- document.body.style.overflow = "hidden";
6395
- scrollLocked = true;
6569
+ lockBodyScroll();
6570
+ scrollHeld = true;
6396
6571
  }
6397
- function unlockBodyScroll() {
6398
- if (!scrollLocked) {
6572
+ function releaseScroll() {
6573
+ if (!scrollHeld) {
6399
6574
  return;
6400
6575
  }
6401
- document.body.style.overflow = previousOverflow;
6402
- previousOverflow = "";
6403
- scrollLocked = false;
6576
+ unlockBodyScroll();
6577
+ scrollHeld = false;
6404
6578
  }
6405
6579
  function restoreFocus() {
6406
6580
  var _a;
@@ -6418,6 +6592,9 @@
6418
6592
  }
6419
6593
  function onKeydown(event) {
6420
6594
  if (event.key === "Escape") {
6595
+ if (!props.closable) {
6596
+ return;
6597
+ }
6421
6598
  event.preventDefault();
6422
6599
  close();
6423
6600
  return;
@@ -6429,19 +6606,23 @@
6429
6606
  vue.watch(
6430
6607
  () => props.modelValue,
6431
6608
  (isOpen) => {
6609
+ if (!isBrowser()) {
6610
+ return;
6611
+ }
6432
6612
  if (isOpen) {
6433
6613
  previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
6434
- lockBodyScroll();
6614
+ holdScroll();
6435
6615
  void focusPanel();
6436
6616
  return;
6437
6617
  }
6438
- unlockBodyScroll();
6618
+ releaseScroll();
6439
6619
  restoreFocus();
6440
6620
  },
6441
6621
  { immediate: true }
6442
6622
  );
6443
6623
  vue.onBeforeUnmount(() => {
6444
- unlockBodyScroll();
6624
+ releaseScroll();
6625
+ restoreFocus();
6445
6626
  });
6446
6627
  return (_ctx, _cache) => {
6447
6628
  return vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
@@ -6502,7 +6683,7 @@
6502
6683
  };
6503
6684
  }
6504
6685
  });
6505
- const TaoDrawer = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-14730fe9"]]);
6686
+ const TaoDrawer = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-10fb02f2"]]);
6506
6687
  const _hoisted_1$7 = ["title"];
6507
6688
  const _hoisted_2$6 = { class: "tao-avatar__face" };
6508
6689
  const _hoisted_3$5 = ["src", "alt"];
@@ -6587,18 +6768,30 @@
6587
6768
  }
6588
6769
  return extra.length ? `${base}, ${extra.join(", ")}` : base;
6589
6770
  });
6771
+ const imgFailed = vue.ref(false);
6772
+ const showImage = vue.computed(() => Boolean(props.src) && !imgFailed.value);
6773
+ vue.watch(
6774
+ () => props.src,
6775
+ () => {
6776
+ imgFailed.value = false;
6777
+ }
6778
+ );
6779
+ function onImgError() {
6780
+ imgFailed.value = true;
6781
+ }
6590
6782
  return (_ctx, _cache) => {
6591
6783
  return vue.openBlock(), vue.createElementBlock("span", {
6592
6784
  class: vue.normalizeClass(["tao-avatar", `tao-avatar--${sizeClass.value}`]),
6593
6785
  title: label.value
6594
6786
  }, [
6595
6787
  vue.createElementVNode("span", _hoisted_2$6, [
6596
- __props.src ? (vue.openBlock(), vue.createElementBlock("img", {
6788
+ showImage.value ? (vue.openBlock(), vue.createElementBlock("img", {
6597
6789
  key: 0,
6598
6790
  class: "tao-avatar__img",
6599
6791
  src: __props.src,
6600
- alt: label.value
6601
- }, null, 8, _hoisted_3$5)) : (vue.openBlock(), vue.createElementBlock("span", {
6792
+ alt: label.value,
6793
+ onError: onImgError
6794
+ }, null, 40, _hoisted_3$5)) : (vue.openBlock(), vue.createElementBlock("span", {
6602
6795
  key: 1,
6603
6796
  class: "tao-avatar__fallback",
6604
6797
  "aria-label": label.value
@@ -6614,7 +6807,7 @@
6614
6807
  };
6615
6808
  }
6616
6809
  });
6617
- const TaoAvatar = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-03b60017"]]);
6810
+ const TaoAvatar = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-65ed2d7a"]]);
6618
6811
  const _hoisted_1$6 = ["aria-label"];
6619
6812
  const _hoisted_2$5 = { class: "tao-breadcrumb__list" };
6620
6813
  const _hoisted_3$4 = {
@@ -6823,7 +7016,8 @@
6823
7016
  return 0;
6824
7017
  }
6825
7018
  const left = ((_a = track.value) == null ? void 0 : _a.scrollLeft) ?? 0;
6826
- return Math.min(Math.max(Math.round(left / (width + gap)), 0), total - 1);
7019
+ const last = Math.max(total - step.value, 0);
7020
+ return Math.min(Math.max(Math.round(left / (width + gap)), 0), last);
6827
7021
  }
6828
7022
  function setIndex(next) {
6829
7023
  if (next === index.value) {
@@ -6874,13 +7068,10 @@
6874
7068
  autoplayTimer = 0;
6875
7069
  }
6876
7070
  function canAutoplay() {
6877
- return props.autoplay > 0 && count.value > step.value && !hoverPaused.value && !focusPaused.value && !dragging.value && typeof document !== "undefined" && !document.hidden && !prefersReducedMotion();
7071
+ return props.autoplay > 0 && count.value > step.value && !hoverPaused.value && !focusPaused.value && !dragging.value && typeof document !== "undefined" && !document.hidden && !prefersReducedMotion() && (props.loop || index.value < lastIndex.value);
6878
7072
  }
6879
7073
  function tickAutoplay() {
6880
7074
  if (!canAutoplay()) {
6881
- return;
6882
- }
6883
- if (!props.loop && index.value >= lastIndex.value) {
6884
7075
  stopAutoplay();
6885
7076
  return;
6886
7077
  }
@@ -6920,7 +7111,14 @@
6920
7111
  }
6921
7112
  cancelAnimationFrame(scrollFrame);
6922
7113
  scrollFrame = requestAnimationFrame(() => {
6923
- setIndex(nearestIndex());
7114
+ const next = nearestIndex();
7115
+ const { width, gap } = metrics();
7116
+ const el = track.value;
7117
+ if (el && width > 0 && el.scrollLeft - next * (width + gap) > (width + gap) / 2) {
7118
+ goTo(next, true);
7119
+ return;
7120
+ }
7121
+ setIndex(next);
6924
7122
  });
6925
7123
  }
6926
7124
  function releaseDragCapture() {
@@ -7025,7 +7223,7 @@
7025
7223
  }
7026
7224
  );
7027
7225
  vue.watch(
7028
- () => [props.autoplay, props.loop, count.value, dragging.value],
7226
+ () => [props.autoplay, props.loop, count.value, dragging.value, index.value],
7029
7227
  () => syncAutoplay()
7030
7228
  );
7031
7229
  vue.onMounted(() => {
@@ -7177,7 +7375,7 @@
7177
7375
  };
7178
7376
  }
7179
7377
  });
7180
- const TaoCarousel = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-239073ed"]]);
7378
+ const TaoCarousel = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-bc396e5d"]]);
7181
7379
  const _hoisted_1$3 = ["aria-label"];
7182
7380
  const _hoisted_2$2 = ["aria-label"];
7183
7381
  const _hoisted_3$2 = {
@@ -7754,14 +7952,13 @@
7754
7952
  __name: "TaoConfirmHost",
7755
7953
  setup(__props) {
7756
7954
  const panelRef = vue.ref(null);
7757
- let previousOverflow = "";
7758
7955
  let previousFocus = null;
7759
- let scrollLocked = false;
7956
+ let scrollHeld = false;
7760
7957
  vue.onMounted(() => {
7761
7958
  registerConfirmHost();
7762
7959
  });
7763
7960
  vue.onBeforeUnmount(() => {
7764
- unlockBodyScroll();
7961
+ releaseScroll();
7765
7962
  unregisterConfirmHost();
7766
7963
  });
7767
7964
  vue.watch(
@@ -7772,12 +7969,15 @@
7772
7969
  async (id) => {
7773
7970
  var _a, _b;
7774
7971
  if (!id) {
7775
- unlockBodyScroll();
7972
+ releaseScroll();
7776
7973
  restoreFocus();
7777
7974
  return;
7778
7975
  }
7976
+ if (!isBrowser()) {
7977
+ return;
7978
+ }
7779
7979
  previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
7780
- lockBodyScroll();
7980
+ holdScroll();
7781
7981
  await vue.nextTick();
7782
7982
  (_b = queryButton(((_a = currentConfirm.value) == null ? void 0 : _a.danger) ? "cancel" : "ok")) == null ? void 0 : _b.focus();
7783
7983
  }
@@ -7786,21 +7986,19 @@
7786
7986
  var _a;
7787
7987
  return ((_a = panelRef.value) == null ? void 0 : _a.querySelector(`[data-tao-confirm-${which}]`)) ?? null;
7788
7988
  }
7789
- function lockBodyScroll() {
7790
- if (scrollLocked) {
7989
+ function holdScroll() {
7990
+ if (scrollHeld || !isBrowser()) {
7791
7991
  return;
7792
7992
  }
7793
- previousOverflow = document.body.style.overflow;
7794
- document.body.style.overflow = "hidden";
7795
- scrollLocked = true;
7993
+ lockBodyScroll();
7994
+ scrollHeld = true;
7796
7995
  }
7797
- function unlockBodyScroll() {
7798
- if (!scrollLocked) {
7996
+ function releaseScroll() {
7997
+ if (!scrollHeld) {
7799
7998
  return;
7800
7999
  }
7801
- document.body.style.overflow = previousOverflow;
7802
- previousOverflow = "";
7803
- scrollLocked = false;
8000
+ unlockBodyScroll();
8001
+ scrollHeld = false;
7804
8002
  }
7805
8003
  function restoreFocus() {
7806
8004
  var _a;
@@ -7814,26 +8012,13 @@
7814
8012
  answer(false);
7815
8013
  }
7816
8014
  function onKeydown(event) {
7817
- var _a, _b;
7818
8015
  if (event.key === "Escape") {
7819
8016
  event.preventDefault();
7820
8017
  answer(false);
7821
8018
  return;
7822
8019
  }
7823
- if (event.key !== "Tab") {
7824
- return;
7825
- }
7826
- const first = queryButton(((_a = currentConfirm.value) == null ? void 0 : _a.danger) ? "cancel" : "ok");
7827
- const last = queryButton(((_b = currentConfirm.value) == null ? void 0 : _b.danger) ? "ok" : "cancel");
7828
- if (!first || !last) {
7829
- return;
7830
- }
7831
- if (event.shiftKey && document.activeElement === first) {
7832
- event.preventDefault();
7833
- last.focus();
7834
- } else if (!event.shiftKey && document.activeElement === last) {
7835
- event.preventDefault();
7836
- first.focus();
8020
+ if (panelRef.value) {
8021
+ trapTab(event, panelRef.value);
7837
8022
  }
7838
8023
  }
7839
8024
  return (_ctx, _cache) => {
@@ -7936,7 +8121,7 @@
7936
8121
  };
7937
8122
  }
7938
8123
  });
7939
- const TaoConfirmHost = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-503301db"]]);
8124
+ const TaoConfirmHost = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d54ae27e"]]);
7940
8125
  const TYPE_TIMEOUT = {
7941
8126
  success: 3e3,
7942
8127
  error: 5e3,