spicykatsu 0.8.0 → 0.9.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 (127) hide show
  1. package/README.md +7 -3
  2. package/dist/SpicyAccordion-CjUXROnD.js +70 -0
  3. package/dist/SpicyAccordion.js +1 -1
  4. package/dist/SpicyBadge-I298Cm9U.js +55 -0
  5. package/dist/SpicyBadge.js +2 -0
  6. package/dist/{SpicyBtn-DQ7A3JOM.js → SpicyBtn-ldAR1VsK.js} +2 -2
  7. package/dist/SpicyBtn.js +1 -1
  8. package/dist/{SpicyDataTable-CLkxtyXn.js → SpicyDataTable-Bj352mv3.js} +3 -3
  9. package/dist/SpicyDataTable.js +1 -1
  10. package/dist/SpicyFileInput-bGUwF-Rj.js +143 -0
  11. package/dist/SpicyFileInput.js +1 -1
  12. package/dist/SpicySelect-D0bg0r5p.js +158 -0
  13. package/dist/SpicySelect.js +2 -0
  14. package/dist/SpicySheet-DL4CsINT.js +47 -0
  15. package/dist/SpicySheet.js +1 -1
  16. package/dist/SpicySkeleton-3pNqXUU-.js +36 -0
  17. package/dist/SpicySkeleton.js +2 -0
  18. package/dist/{SpicyTextArea-CxEDRJ1P.js → SpicyTextArea-BL78Bqs3.js} +23 -5
  19. package/dist/SpicyTextArea.js +1 -1
  20. package/dist/{SpicyTextField-sziwr-ns.js → SpicyTextField-4W0cSxVp.js} +25 -9
  21. package/dist/SpicyTextField.js +1 -1
  22. package/dist/SpicyToast-DH31y-Hx.js +74 -0
  23. package/dist/SpicyToast.js +2 -0
  24. package/dist/SpicyTooltip-K6dAoHrQ.js +97 -0
  25. package/dist/SpicyTooltip.js +1 -1
  26. package/dist/index.js +55 -47
  27. package/dist/spicyDrag-BM9QhUAJ.js +67 -0
  28. package/dist/spicyDrag.js +1 -1
  29. package/dist/spicyRipple-BCGepSKc.js +49 -0
  30. package/dist/spicyRipple.js +1 -1
  31. package/dist/spicykatsu.css +1 -1
  32. package/dist/spicykatsu.umd.js +1 -1
  33. package/dist/styles/SpicyAccordion.css +1 -1
  34. package/dist/styles/SpicyBadge.css +1 -0
  35. package/dist/styles/SpicyBtn.css +1 -1
  36. package/dist/styles/SpicyFileInput.css +1 -1
  37. package/dist/styles/SpicySelect.css +1 -0
  38. package/dist/styles/SpicySheet.css +1 -1
  39. package/dist/styles/SpicySkeleton.css +1 -0
  40. package/dist/styles/SpicyTextArea.css +1 -1
  41. package/dist/styles/SpicyTextField.css +1 -1
  42. package/dist/styles/SpicyToast.css +1 -0
  43. package/dist/styles/SpicyTooltip.css +1 -1
  44. package/dist/types/components/SpicyAccordion/SpicyAccordion.vue.d.ts +3 -0
  45. package/dist/types/components/SpicyBadge/SpicyBadge.vue.d.ts +34 -0
  46. package/dist/types/components/SpicyBtn/SpicyBtn.vue.d.ts +3 -3
  47. package/dist/types/components/SpicyDivider/SpicyDivider.vue.d.ts +1 -1
  48. package/dist/types/components/SpicyFileInput/SpicyFileInput.vue.d.ts +5 -1
  49. package/dist/types/components/SpicyModal/SpicyModal.vue.d.ts +1 -1
  50. package/dist/types/components/SpicyProgress/SpicyProgress.vue.d.ts +1 -1
  51. package/dist/types/components/SpicySelect/SpicySelect.vue.d.ts +33 -0
  52. package/dist/types/components/SpicySheet/SpicySheet.vue.d.ts +16 -2
  53. package/dist/types/components/SpicySkeleton/SpicySkeleton.vue.d.ts +18 -0
  54. package/dist/types/components/SpicySlider/SpicySlider.vue.d.ts +1 -1
  55. package/dist/types/components/SpicyTextArea/SpicyTextArea.vue.d.ts +12 -0
  56. package/dist/types/components/SpicyTextField/SpicyTextField.vue.d.ts +8 -0
  57. package/dist/types/components/SpicyToast/SpicyToast.vue.d.ts +8 -0
  58. package/dist/types/components/SpicyToast/useToast.d.ts +28 -0
  59. package/dist/types/components/SpicyToggle/SpicyToggle.vue.d.ts +1 -1
  60. package/dist/types/components/SpicyTooltip/SpicyTooltip.vue.d.ts +13 -1
  61. package/dist/types/directives/spicyDrag.d.ts +7 -0
  62. package/dist/types/directives/spicyRipple.d.ts +6 -1
  63. package/dist/types/entries/SpicyBadge.d.ts +2 -0
  64. package/dist/types/entries/SpicySelect.d.ts +2 -0
  65. package/dist/types/entries/SpicySkeleton.d.ts +2 -0
  66. package/dist/types/entries/SpicyToast.d.ts +3 -0
  67. package/dist/types/index.d.ts +5 -1
  68. package/package.json +3 -3
  69. package/dist/SpicyAccordion-Cm-RI3r_.js +0 -47
  70. package/dist/SpicyAccordion-TUM16yOu.js +0 -50
  71. package/dist/SpicyAlert-BD6QHaFZ.js +0 -100
  72. package/dist/SpicyAlert-Bwi92wCd.js +0 -99
  73. package/dist/SpicyBtn-B5nk3vCZ.js +0 -81
  74. package/dist/SpicyCarousel-Be5oYKnj.js +0 -121
  75. package/dist/SpicyCarousel-CkCmK2tQ.js +0 -123
  76. package/dist/SpicyCarousel-DGtg0K1L.js +0 -123
  77. package/dist/SpicyDataTable-BqoW4IZ4.js +0 -126
  78. package/dist/SpicyDataTable-x2bGAZMS.js +0 -129
  79. package/dist/SpicyDialog-CKtIwcPz.js +0 -45
  80. package/dist/SpicyDropdown-COCmOTvv.js +0 -66
  81. package/dist/SpicyDropdown-CkpSJleZ.js +0 -64
  82. package/dist/SpicyDropdown-DLqjiK7t.js +0 -63
  83. package/dist/SpicyDropdown-DYtCUZwE.js +0 -67
  84. package/dist/SpicyFileInput-7dwibTqM.js +0 -126
  85. package/dist/SpicyFileInput-Cm8fYpHV.js +0 -139
  86. package/dist/SpicyFileInput-CnO7Pecq.js +0 -130
  87. package/dist/SpicyFileInput-Dkgt7474.js +0 -132
  88. package/dist/SpicyModal-Dx4dKN4V.js +0 -96
  89. package/dist/SpicyProgress-CjD0SCA7.js +0 -76
  90. package/dist/SpicySheet-k07oHm4-.js +0 -33
  91. package/dist/SpicySlider-CGNWDfwv.js +0 -63
  92. package/dist/SpicySlider-DPgJ_VLR.js +0 -61
  93. package/dist/SpicyTabs-8fPN5eaX.js +0 -71
  94. package/dist/SpicyTabs-BHIwFnvt.js +0 -67
  95. package/dist/SpicyTabs-DmB1xuWN.js +0 -66
  96. package/dist/SpicyTabs-DrrGbixN.js +0 -67
  97. package/dist/SpicyTextArea-BqgEgEyx.js +0 -36
  98. package/dist/SpicyTextField-BMX1T6xl.js +0 -97
  99. package/dist/SpicyToggle-C-JcmPvu.js +0 -55
  100. package/dist/SpicyToggle-DJTopuIB.js +0 -55
  101. package/dist/SpicyTooltip-8nWZNAvJ.js +0 -75
  102. package/dist/SpicyTooltip-CE8Cg0wo.js +0 -80
  103. package/dist/SpicyTooltip-aBB5NaKu.js +0 -81
  104. package/dist/spicyDrag-BLiL2y_4.js +0 -38
  105. package/dist/spicyDrag-CgD0GOa9.js +0 -38
  106. package/dist/spicyRipple-CViURy7j.js +0 -43
  107. package/dist/spicyRipple-DHAFwamp.js +0 -43
  108. package/dist/spicyRipple-DcEibbQv.js +0 -42
  109. package/dist/types/components/SpicyAccordion/SpicyAccordion.test.d.ts +0 -1
  110. package/dist/types/components/SpicyAlert/SpicyAlert.test.d.ts +0 -1
  111. package/dist/types/components/SpicyBtn/SpicyBtn.test.d.ts +0 -1
  112. package/dist/types/components/SpicyCarousel/SpicyCarousel.test.d.ts +0 -1
  113. package/dist/types/components/SpicyDataTable/SpicyDataTable.test.d.ts +0 -1
  114. package/dist/types/components/SpicyDialog/SpicyDialog.test.d.ts +0 -1
  115. package/dist/types/components/SpicyDivider/SpicyDivider.test.d.ts +0 -1
  116. package/dist/types/components/SpicyDropdown/SpicyDropdown.test.d.ts +0 -1
  117. package/dist/types/components/SpicyFileInput/SpicyFileInput.test.d.ts +0 -1
  118. package/dist/types/components/SpicyModal/SpicyModal.test.d.ts +0 -1
  119. package/dist/types/components/SpicyProgress/SpicyProgress.test.d.ts +0 -1
  120. package/dist/types/components/SpicySheet/SpicySheet.test.d.ts +0 -1
  121. package/dist/types/components/SpicySlider/SpicySlider.test.d.ts +0 -1
  122. package/dist/types/components/SpicyTabs/SpicyTabs.test.d.ts +0 -1
  123. package/dist/types/components/SpicyTextArea/SpicyTextArea.test.d.ts +0 -1
  124. package/dist/types/components/SpicyTextField/SpicyTextField.test.d.ts +0 -1
  125. package/dist/types/components/SpicyToggle/SpicyToggle.test.d.ts +0 -1
  126. package/dist/types/components/SpicyTooltip/SpicyTooltip.test.d.ts +0 -1
  127. package/dist/types/components/SpicyTree/SpicyTree.test.d.ts +0 -1
package/README.md CHANGED
@@ -90,6 +90,7 @@ app.use(SpicyKatsu, { useComponents: false, useStyles: 'variables' })
90
90
  |-----------|-------------|
91
91
  | `SpicyAccordion` | Collapsible sections, single or multi-open |
92
92
  | `SpicyAlert` | Dismissible alerts with variants and auto-close |
93
+ | `SpicyBadge` | Pill/tag badges with variants, dot, and removable |
93
94
  | `SpicyBtn` | Button with MDI icon support and ripple effect |
94
95
  | `SpicyCarousel` | Image carousel with autoplay, touch, and pagination |
95
96
  | `SpicyDataTable` | Data table with sorting, filtering, and pagination |
@@ -99,11 +100,14 @@ app.use(SpicyKatsu, { useComponents: false, useStyles: 'variables' })
99
100
  | `SpicyFileInput` | File input with drag-and-drop and multi-file preview |
100
101
  | `SpicyModal` | Modal dialog with title, actions, and Escape-to-close |
101
102
  | `SpicyProgress` | Linear and circular progress indicators |
103
+ | `SpicySelect` | Custom select with search, multi-select, and keyboard nav |
102
104
  | `SpicySheet` | Styled container/card |
105
+ | `SpicySkeleton` | Loading placeholder with shimmer animation |
103
106
  | `SpicySlider` | Range slider input |
104
107
  | `SpicyTabs` | Tabbed interface with scrollable tab bar |
105
108
  | `SpicyTextArea` | Styled textarea |
106
109
  | `SpicyTextField` | Text input with floating label, prefix, and validation |
110
+ | `SpicyToast` | Toast notification system with auto-dismiss and positions |
107
111
  | `SpicyToggle` | Toggle switch |
108
112
  | `SpicyTooltip` | Hover tooltip with position control |
109
113
  | `SpicyTree` | Recursive tree view |
@@ -112,8 +116,8 @@ app.use(SpicyKatsu, { useComponents: false, useStyles: 'variables' })
112
116
 
113
117
  | Directive | Description |
114
118
  |-----------|-------------|
115
- | `v-spicyDrag` | Makes any element draggable (mouse + touch). Accepts `{ axis: 'x' | 'y' }` |
116
- | `v-spicyRipple` | Adds a Material-style ripple on click/touch |
119
+ | `v-spicyDrag` | Makes any element draggable (mouse + touch). Options: `axis`, `handle`, `disabled`, `bounds`, `grid`, `onDragStart`, `onDrag`, `onDragEnd` |
120
+ | `v-spicyRipple` | Adds a Material-style ripple on click/touch. Options: `color`, `center`. Use `data-no-ripple` to disable |
117
121
 
118
122
  ## Dev / Playground
119
123
 
@@ -124,4 +128,4 @@ bun install
124
128
  bun run dev
125
129
  ```
126
130
 
127
- The playground (`src/playground/Playground.vue`) has a live example of every component and directive.
131
+ The playground (`playground/Playground.vue`) has a live example of every component and directive.
@@ -0,0 +1,70 @@
1
+ import { Fragment as e, Transition as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createVNode as a, defineComponent as o, normalizeClass as s, openBlock as c, ref as l, renderList as u, renderSlot as d, toDisplayString as f, withCtx as p } from "vue";
2
+ //#region src/components/SpicyAccordion/SpicyAccordion.vue?vue&type=script&setup=true&lang.ts
3
+ var m = [
4
+ "onClick",
5
+ "aria-expanded",
6
+ "aria-controls",
7
+ "disabled"
8
+ ], h = {
9
+ key: 0,
10
+ class: "accordionIcon",
11
+ viewBox: "0 0 24 24",
12
+ xmlns: "http://www.w3.org/2000/svg"
13
+ }, g = ["d"], _ = ["id"], v = /* @__PURE__ */ o({
14
+ __name: "SpicyAccordion",
15
+ props: {
16
+ sections: {},
17
+ singleOpen: {
18
+ type: Boolean,
19
+ default: !1
20
+ },
21
+ defaultOpen: {},
22
+ disabled: {
23
+ type: Boolean,
24
+ default: !1
25
+ }
26
+ },
27
+ setup(o) {
28
+ let v = o, y = l(v.defaultOpen || []), b = (e) => {
29
+ if (!(v.disabled || v.sections[e]?.disabled)) if (v.singleOpen) y.value = y.value.includes(e) ? [] : [e];
30
+ else {
31
+ let t = y.value.indexOf(e);
32
+ t === -1 ? y.value.push(e) : y.value.splice(t, 1);
33
+ }
34
+ }, x = (e) => y.value.includes(e);
35
+ return (l, v) => (c(), r("div", { class: s(["spicyAccordion", { disabled: o.disabled }]) }, [(c(!0), r(e, null, u(o.sections, (e, u) => (c(), r("div", {
36
+ key: u,
37
+ class: "spicyAccordionItem"
38
+ }, [i("button", {
39
+ type: "button",
40
+ class: s(["spicyAccordionHeader", { open: x(u) }]),
41
+ onClick: (e) => b(u),
42
+ "aria-expanded": x(u),
43
+ "aria-controls": `accordion-panel-${u}`,
44
+ disabled: o.disabled || e.disabled
45
+ }, [
46
+ i("span", null, f(e.title), 1),
47
+ e.icon ? (c(), r("svg", h, [i("path", {
48
+ fill: "currentColor",
49
+ d: e.icon
50
+ }, null, 8, g)])) : n("", !0),
51
+ v[0] ||= i("span", { class: "accordionToggle" }, [i("svg", {
52
+ class: "accordionArrow",
53
+ viewBox: "0 0 24 24"
54
+ }, [i("path", {
55
+ fill: "currentColor",
56
+ d: "M7 10l5 5 5-5H7z"
57
+ })])], -1)
58
+ ], 10, m), a(t, { name: "accordion-slide" }, {
59
+ default: p(() => [x(u) ? (c(), r("div", {
60
+ key: 0,
61
+ id: `accordion-panel-${u}`,
62
+ class: "spicyAccordionContent",
63
+ role: "region"
64
+ }, [d(l.$slots, `section-${u}`)], 8, _)) : n("", !0)]),
65
+ _: 2
66
+ }, 1024)]))), 128))], 2));
67
+ }
68
+ });
69
+ //#endregion
70
+ export { v as t };
@@ -1,2 +1,2 @@
1
- import { t as e } from "./SpicyAccordion-TUM16yOu.js";
1
+ import { t as e } from "./SpicyAccordion-CjUXROnD.js";
2
2
  export { e as SpicyAccordion, e as default };
@@ -0,0 +1,55 @@
1
+ import { computed as e, createCommentVNode as t, createElementBlock as n, defineComponent as r, normalizeClass as i, normalizeStyle as a, openBlock as o, renderSlot as s } from "vue";
2
+ //#endregion
3
+ //#region src/components/SpicyBadge/SpicyBadge.vue
4
+ var c = /* @__PURE__ */ r({
5
+ __name: "SpicyBadge",
6
+ props: {
7
+ variant: { default: "soft" },
8
+ color: { default: "" },
9
+ textColor: { default: "" },
10
+ size: { default: "md" },
11
+ dot: {
12
+ type: Boolean,
13
+ default: !1
14
+ },
15
+ dotColor: { default: "" },
16
+ removable: {
17
+ type: Boolean,
18
+ default: !1
19
+ }
20
+ },
21
+ emits: ["remove"],
22
+ setup(r) {
23
+ let c = r, l = e(() => c.dot), u = e(() => {
24
+ let e = {};
25
+ return c.color && (c.variant === "solid" ? e.backgroundColor = c.color : c.variant === "outlined" ? (e.borderColor = c.color, e.color = c.color) : (e.backgroundColor = `color-mix(in srgb, ${c.color} 15%, transparent)`, e.color = c.color)), c.textColor && (e.color = c.textColor), e;
26
+ });
27
+ return (e, c) => (o(), n("span", {
28
+ class: i(["spicyBadge", [
29
+ r.variant,
30
+ r.size,
31
+ {
32
+ dot: l.value,
33
+ removable: r.removable
34
+ }
35
+ ]]),
36
+ style: a(u.value)
37
+ }, [
38
+ l.value ? (o(), n("span", {
39
+ key: 0,
40
+ class: "spicyBadgeDot",
41
+ style: a({ backgroundColor: r.dotColor })
42
+ }, null, 4)) : t("", !0),
43
+ s(e.$slots, "default"),
44
+ r.removable ? (o(), n("button", {
45
+ key: 1,
46
+ class: "spicyBadgeRemove",
47
+ onClick: c[0] ||= (t) => e.$emit("remove"),
48
+ "aria-label": "Remove badge",
49
+ type: "button"
50
+ }, " ✕ ")) : t("", !0)
51
+ ], 6));
52
+ }
53
+ });
54
+ //#endregion
55
+ export { c as t };
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./SpicyBadge-I298Cm9U.js";
2
+ export { e as SpicyBadge, e as default };
@@ -27,7 +27,7 @@ var f = [
27
27
  text: {},
28
28
  icon: {},
29
29
  mdi: {},
30
- size: { default: "default" },
30
+ size: { default: "md" },
31
31
  bgColor: {},
32
32
  textColor: { default: "#ddd" },
33
33
  hoverColor: {},
@@ -52,7 +52,7 @@ var f = [
52
52
  outlined: b.variant === "outlined",
53
53
  disabled: b.disabled,
54
54
  isRound: C.value,
55
- [b.size]: b.size !== "default"
55
+ [b.size]: b.size !== "md"
56
56
  }));
57
57
  return (e, _) => {
58
58
  let v = l("spicyRipple");
package/dist/SpicyBtn.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as e } from "./SpicyBtn-DQ7A3JOM.js";
1
+ import { t as e } from "./SpicyBtn-ldAR1VsK.js";
2
2
  export { e as SpicyBtn, e as default };
@@ -1,4 +1,4 @@
1
- import { t as e } from "./SpicyBtn-DQ7A3JOM.js";
1
+ import { t as e } from "./SpicyBtn-ldAR1VsK.js";
2
2
  import { t } from "./SpicyProgress-62dbvFg1.js";
3
3
  import { Fragment as n, computed as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, defineComponent as l, normalizeClass as u, normalizeStyle as d, openBlock as f, ref as p, renderList as m, renderSlot as h, toDisplayString as g, watch as _ } from "vue";
4
4
  //#region src/components/SpicyDataTable/SpicyDataTable.vue?vue&type=script&setup=true&lang.ts
@@ -106,12 +106,12 @@ var v = { class: "spicyDataTable" }, y = { class: "spicyDataTableContainer" }, b
106
106
  disabled: z.value === 1,
107
107
  onClick: Y,
108
108
  text: "Previous",
109
- size: "small"
109
+ size: "sm"
110
110
  }, null, 8, ["disabled"]), c(e, {
111
111
  disabled: z.value === W.value,
112
112
  onClick: X,
113
113
  text: "Next",
114
- size: "small"
114
+ size: "sm"
115
115
  }, null, 8, ["disabled"])]),
116
116
  o("div", j, [o("select", {
117
117
  value: B.value,
@@ -1,2 +1,2 @@
1
- import { t as e } from "./SpicyDataTable-CLkxtyXn.js";
1
+ import { t as e } from "./SpicyDataTable-Bj352mv3.js";
2
2
  export { e as SpicyDataTable, e as default };
@@ -0,0 +1,143 @@
1
+ import { Fragment as e, createCommentVNode as t, createElementBlock as n, createElementVNode as r, defineComponent as i, normalizeClass as a, openBlock as o, ref as s, renderList as c, renderSlot as l, toDisplayString as u, watch as d, withModifiers as f } from "vue";
2
+ //#region src/components/SpicyFileInput/SpicyFileInput.vue?vue&type=script&setup=true&lang.ts
3
+ var p = ["aria-label"], m = [
4
+ "multiple",
5
+ "accept",
6
+ "name",
7
+ "disabled",
8
+ "aria-label"
9
+ ], h = {
10
+ key: 1,
11
+ class: "spicyFilePreview"
12
+ }, g = { class: "spicyFilePreviewName" }, _ = ["onClick"], v = ["onClick"], y = {
13
+ viewBox: "0 0 24 24",
14
+ xmlns: "http://www.w3.org/2000/svg"
15
+ }, b = ["d"], x = {
16
+ key: 3,
17
+ class: "spicyFileInputError"
18
+ }, S = /* @__PURE__ */ i({
19
+ __name: "SpicyFileInput",
20
+ props: {
21
+ modelValue: { default: () => [] },
22
+ label: { default: "" },
23
+ error: { default: "" },
24
+ accept: { default: "" },
25
+ multiple: {
26
+ type: Boolean,
27
+ default: !1
28
+ },
29
+ clearable: {
30
+ type: Boolean,
31
+ default: !1
32
+ },
33
+ disabled: {
34
+ type: Boolean,
35
+ default: !1
36
+ },
37
+ mdi: { default: "" },
38
+ variant: { default: "dashed" },
39
+ name: { default: "" },
40
+ ariaLabel: { default: "" }
41
+ },
42
+ emits: [
43
+ "update:modelValue",
44
+ "change",
45
+ "error"
46
+ ],
47
+ setup(i, { emit: S }) {
48
+ let C = S, w = i, T = s(w.modelValue), E = s(null), D = s(!1);
49
+ d(() => w.modelValue, (e) => {
50
+ T.value = e;
51
+ });
52
+ let O = (e) => {
53
+ if (!w.accept) return e;
54
+ let t = w.accept.split(",").map((e) => e.trim());
55
+ return e.filter((e) => t.some((t) => t.startsWith(".") ? e.name.endsWith(t) : e.type === t));
56
+ }, k = (e) => {
57
+ let t = O(e);
58
+ t.length < e.length && C("error", `${e.length - t.length} file(s) were rejected due to type restrictions`), !w.multiple && t.length > 0 ? (T.value = [t[0]], t.length > 1 && C("error", "Only one file is allowed")) : T.value = t, C("update:modelValue", T.value), C("change", T.value);
59
+ }, A = (e) => {
60
+ let t = e.target;
61
+ t.files && k(Array.from(t.files));
62
+ }, j = () => {
63
+ T.value = [], C("update:modelValue", T.value), C("change", T.value), E.value && (E.value.value = "");
64
+ }, M = (e) => {
65
+ T.value.splice(e, 1), C("update:modelValue", T.value), T.value.length === 0 && E.value && (E.value.value = ""), C("change", T.value);
66
+ }, N = () => {
67
+ w.disabled || E.value?.click();
68
+ }, P = () => {
69
+ w.disabled || (D.value = !0);
70
+ }, F = () => {
71
+ w.disabled || (D.value = !1);
72
+ }, I = (e) => {
73
+ if (!w.disabled) {
74
+ let t = e.dataTransfer?.files;
75
+ t && k(Array.from(t)), D.value = !1;
76
+ }
77
+ };
78
+ return (s, d) => (o(), n("div", {
79
+ class: a(["spicyFileInputWrapper", [{
80
+ hasError: i.error,
81
+ isDragging: D.value,
82
+ disabled: i.disabled,
83
+ [i.variant]: i.variant
84
+ }]]),
85
+ onClick: N,
86
+ onDragover: f(P, ["prevent"]),
87
+ onDragleave: f(F, ["prevent"]),
88
+ onDrop: f(I, ["prevent"])
89
+ }, [
90
+ i.label && !T.value.length ? (o(), n("label", {
91
+ key: 0,
92
+ class: "spicyFileInputLabel",
93
+ "aria-label": i.label
94
+ }, u(i.label), 9, p)) : t("", !0),
95
+ r("input", {
96
+ type: "file",
97
+ multiple: i.multiple,
98
+ accept: i.accept,
99
+ name: i.name,
100
+ class: "spicyFileInput",
101
+ onChange: A,
102
+ ref_key: "fileInput",
103
+ ref: E,
104
+ disabled: i.disabled,
105
+ "aria-label": i.ariaLabel || i.label || "File input"
106
+ }, null, 40, m),
107
+ T.value.length ? (o(), n("div", h, [(o(!0), n(e, null, c(T.value, (e, a) => (o(), n("div", {
108
+ key: a,
109
+ class: "spicyFilePreviewItem"
110
+ }, [
111
+ r("span", g, u(e.name), 1),
112
+ i.clearable && !i.mdi && !i.disabled ? (o(), n("button", {
113
+ key: 0,
114
+ class: "removeButton",
115
+ onClick: f((e) => M(a), ["stop"]),
116
+ "aria-label": "Remove file",
117
+ type: "button"
118
+ }, " ✕ ", 8, _)) : t("", !0),
119
+ i.clearable && i.mdi && !i.disabled ? (o(), n("button", {
120
+ key: 1,
121
+ class: "removeButtonMDI",
122
+ onClick: f((e) => M(a), ["stop"]),
123
+ "aria-label": "Remove file",
124
+ type: "button"
125
+ }, [(o(), n("svg", y, [r("path", {
126
+ fill: "currentColor",
127
+ d: i.mdi
128
+ }, null, 8, b)]))], 8, v)) : t("", !0)
129
+ ]))), 128))])) : t("", !0),
130
+ i.clearable && T.value.length > 1 && !i.disabled ? (o(), n("button", {
131
+ key: 2,
132
+ class: "clearAllButton",
133
+ onClick: f(j, ["stop"]),
134
+ "aria-label": "Clear all files",
135
+ type: "button"
136
+ }, " Clear All ")) : t("", !0),
137
+ l(s.$slots, "default"),
138
+ i.error ? (o(), n("span", x, u(i.error), 1)) : t("", !0)
139
+ ], 34));
140
+ }
141
+ });
142
+ //#endregion
143
+ export { S as t };
@@ -1,2 +1,2 @@
1
- import { t as e } from "./SpicyFileInput-Cm8fYpHV.js";
1
+ import { t as e } from "./SpicyFileInput-bGUwF-Rj.js";
2
2
  export { e as SpicyFileInput, e as default };
@@ -0,0 +1,158 @@
1
+ import { Fragment as e, Transition as t, computed as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createVNode as o, defineComponent as s, nextTick as c, normalizeClass as l, onMounted as u, onUnmounted as d, openBlock as f, ref as p, renderList as m, toDisplayString as h, useId as g, vModelText as _, watch as v, withCtx as y, withDirectives as b, withKeys as x, withModifiers as S } from "vue";
2
+ //#region src/components/SpicySelect/SpicySelect.vue?vue&type=script&setup=true&lang.ts
3
+ var C = { class: "spicySelectContainer" }, w = [
4
+ "disabled",
5
+ "aria-expanded",
6
+ "aria-label"
7
+ ], T = { class: "spicySelectValue" }, E = {
8
+ key: 0,
9
+ class: "spicySelectDropdown"
10
+ }, D = {
11
+ key: 0,
12
+ class: "spicySelectSearch"
13
+ }, O = ["onKeydown"], k = {
14
+ class: "spicySelectOptions",
15
+ role: "listbox"
16
+ }, A = [
17
+ "aria-selected",
18
+ "onClick",
19
+ "onMouseenter"
20
+ ], j = {
21
+ key: 0,
22
+ class: "spicySelectCheck",
23
+ viewBox: "0 0 24 24"
24
+ }, M = {
25
+ key: 0,
26
+ class: "spicySelectEmpty"
27
+ }, N = {
28
+ key: 1,
29
+ class: "spicySelectError"
30
+ }, P = /* @__PURE__ */ s({
31
+ __name: "SpicySelect",
32
+ props: {
33
+ modelValue: { default: "" },
34
+ options: {},
35
+ label: { default: "" },
36
+ placeholder: { default: "Select an option" },
37
+ error: { default: "" },
38
+ disabled: {
39
+ type: Boolean,
40
+ default: !1
41
+ },
42
+ searchable: {
43
+ type: Boolean,
44
+ default: !1
45
+ },
46
+ multiple: {
47
+ type: Boolean,
48
+ default: !1
49
+ },
50
+ ariaLabel: { default: "" }
51
+ },
52
+ emits: ["update:modelValue", "change"],
53
+ setup(s, { emit: P }) {
54
+ let F = s, I = P, L = `spicySelect_${g()}`, R = p(null), z = p(null), B = p(!1), V = p(""), H = p(0), U = n(() => {
55
+ if (!V.value) return F.options;
56
+ let e = V.value.toLowerCase();
57
+ return F.options.filter((t) => t.label.toLowerCase().includes(e));
58
+ }), W = n(() => {
59
+ if (F.multiple) {
60
+ let e = F.modelValue;
61
+ return !e || !e.length ? "" : e.map((e) => F.options.find((t) => t.value === e)?.label).filter(Boolean).join(", ");
62
+ }
63
+ let e = F.modelValue;
64
+ return F.options.find((t) => t.value === e)?.label || "";
65
+ }), G = (e) => F.multiple ? F.modelValue.includes(e.value) : F.modelValue === e.value, K = (e) => {
66
+ if (F.multiple) {
67
+ let t = [...F.modelValue], n = t.indexOf(e.value);
68
+ n === -1 ? t.push(e.value) : t.splice(n, 1), I("update:modelValue", t), I("change", t);
69
+ } else I("update:modelValue", e.value), I("change", e.value), Y();
70
+ }, q = () => {
71
+ F.disabled || (B.value ? Y() : J());
72
+ }, J = () => {
73
+ B.value = !0, H.value = 0, F.searchable && c(() => z.value?.focus());
74
+ }, Y = () => {
75
+ B.value = !1, V.value = "";
76
+ }, X = () => {
77
+ H.value < U.value.length - 1 && H.value++;
78
+ }, Z = () => {
79
+ H.value > 0 && H.value--;
80
+ }, Q = () => {
81
+ U.value[H.value] && K(U.value[H.value]);
82
+ }, $ = (e) => {
83
+ R.value && !R.value.contains(e.target) && Y();
84
+ };
85
+ return u(() => {
86
+ document.addEventListener("click", $);
87
+ }), d(() => {
88
+ document.removeEventListener("click", $);
89
+ }), v(B, (e) => {
90
+ e || (V.value = "");
91
+ }), (n, c) => (f(), i("div", {
92
+ class: l(["spicySelectWrapper", {
93
+ disabled: s.disabled,
94
+ hasError: s.error,
95
+ isOpen: B.value
96
+ }]),
97
+ ref_key: "wrapperRef",
98
+ ref: R
99
+ }, [
100
+ s.label ? (f(), i("label", {
101
+ key: 0,
102
+ class: "spicySelectLabel",
103
+ for: L
104
+ }, h(s.label), 1)) : r("", !0),
105
+ a("div", C, [a("button", {
106
+ type: "button",
107
+ class: l(["spicySelectTrigger", {
108
+ hasValue: W.value,
109
+ placeholder: !W.value
110
+ }]),
111
+ onClick: q,
112
+ disabled: s.disabled,
113
+ id: L,
114
+ "aria-expanded": B.value,
115
+ "aria-haspopup": "listbox",
116
+ "aria-label": s.ariaLabel || s.label || void 0
117
+ }, [a("span", T, h(W.value || s.placeholder), 1), c[1] ||= a("svg", {
118
+ class: "spicySelectArrow",
119
+ viewBox: "0 0 24 24"
120
+ }, [a("path", {
121
+ fill: "currentColor",
122
+ d: "M7 10l5 5 5-5H7z"
123
+ })], -1)], 10, w), o(t, { name: "spicySelect-slide" }, {
124
+ default: y(() => [B.value ? (f(), i("div", E, [s.searchable ? (f(), i("div", D, [b(a("input", {
125
+ type: "text",
126
+ class: "spicySelectSearchInput",
127
+ "onUpdate:modelValue": c[0] ||= (e) => V.value = e,
128
+ placeholder: "Search...",
129
+ ref_key: "searchInputRef",
130
+ ref: z,
131
+ onKeydown: [
132
+ x(S(X, ["prevent"]), ["down"]),
133
+ x(S(Z, ["prevent"]), ["up"]),
134
+ x(S(Q, ["prevent"]), ["enter"]),
135
+ x(S(Y, ["prevent"]), ["escape"])
136
+ ]
137
+ }, null, 40, O), [[_, V.value]])])) : r("", !0), a("ul", k, [(f(!0), i(e, null, m(U.value, (e, t) => (f(), i("li", {
138
+ key: e.value,
139
+ class: l(["spicySelectOption", {
140
+ selected: G(e),
141
+ highlighted: t === H.value
142
+ }]),
143
+ role: "option",
144
+ "aria-selected": G(e),
145
+ onClick: (t) => K(e),
146
+ onMouseenter: (e) => H.value = t
147
+ }, [a("span", null, h(e.label), 1), G(e) ? (f(), i("svg", j, [...c[2] ||= [a("path", {
148
+ fill: "currentColor",
149
+ d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"
150
+ }, null, -1)]])) : r("", !0)], 42, A))), 128)), U.value.length === 0 ? (f(), i("li", M, "No options found")) : r("", !0)])])) : r("", !0)]),
151
+ _: 1
152
+ })]),
153
+ s.error ? (f(), i("span", N, h(s.error), 1)) : r("", !0)
154
+ ], 2));
155
+ }
156
+ });
157
+ //#endregion
158
+ export { P as t };
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./SpicySelect-D0bg0r5p.js";
2
+ export { e as SpicySelect, e as default };
@@ -0,0 +1,47 @@
1
+ import { computed as e, createBlock as t, defineComponent as n, normalizeClass as r, normalizeStyle as i, openBlock as a, renderSlot as o, resolveDynamicComponent as s, withCtx as c } from "vue";
2
+ //#endregion
3
+ //#region src/components/SpicySheet/SpicySheet.vue
4
+ var l = /* @__PURE__ */ n({
5
+ __name: "SpicySheet",
6
+ props: {
7
+ isRound: {
8
+ type: Boolean,
9
+ default: !1
10
+ },
11
+ color: { default: "" },
12
+ padding: { default: "" },
13
+ flex: {
14
+ type: Boolean,
15
+ default: !1
16
+ },
17
+ elevation: { default: 0 },
18
+ gap: { default: "" },
19
+ width: { default: "" },
20
+ maxWidth: { default: "" },
21
+ border: { default: "" },
22
+ borderRadius: { default: "" },
23
+ tag: { default: "div" }
24
+ },
25
+ setup(n) {
26
+ let l = n, u = e(() => l.elevation ? `elevation-${l.elevation}` : ""), d = e(() => {
27
+ let e = {};
28
+ return l.color && (e.backgroundColor = l.color), l.padding && (e.padding = l.padding), l.gap && (e["--sheet-gap"] = l.gap), l.width && (e.width = l.width), l.maxWidth && (e.maxWidth = l.maxWidth), l.border && (e.border = l.border), l.borderRadius && (e.borderRadius = l.borderRadius), e;
29
+ });
30
+ return (e, l) => (a(), t(s(n.tag), {
31
+ class: r([
32
+ "spicySheet",
33
+ {
34
+ isRound: n.isRound && !n.borderRadius,
35
+ flex: n.flex
36
+ },
37
+ u.value
38
+ ]),
39
+ style: i(d.value)
40
+ }, {
41
+ default: c(() => [o(e.$slots, "default")]),
42
+ _: 3
43
+ }, 8, ["class", "style"]));
44
+ }
45
+ });
46
+ //#endregion
47
+ export { l as t };
@@ -1,2 +1,2 @@
1
- import { t as e } from "./SpicySheet-k07oHm4-.js";
1
+ import { t as e } from "./SpicySheet-DL4CsINT.js";
2
2
  export { e as SpicySheet, e as default };
@@ -0,0 +1,36 @@
1
+ import { computed as e, createElementBlock as t, defineComponent as n, normalizeClass as r, normalizeStyle as i, openBlock as a } from "vue";
2
+ //#endregion
3
+ //#region src/components/SpicySkeleton/SpicySkeleton.vue
4
+ var o = /* @__PURE__ */ n({
5
+ __name: "SpicySkeleton",
6
+ props: {
7
+ width: { default: "100%" },
8
+ height: { default: "1em" },
9
+ variant: { default: "rect" },
10
+ rounded: {
11
+ type: Boolean,
12
+ default: !1
13
+ },
14
+ color: { default: "" },
15
+ shimmer: {
16
+ type: Boolean,
17
+ default: !0
18
+ }
19
+ },
20
+ setup(n) {
21
+ let o = n, s = e(() => ({
22
+ width: o.width,
23
+ height: o.height,
24
+ ...o.color ? { "--skSkeletonColor": o.color } : {},
25
+ ...o.shimmer ? {} : { animation: "none" }
26
+ }));
27
+ return (e, o) => (a(), t("div", {
28
+ class: r(["spicySkeleton", [n.variant, { rounded: n.rounded }]]),
29
+ style: i(s.value),
30
+ role: "status",
31
+ "aria-label": "Loading"
32
+ }, null, 6));
33
+ }
34
+ });
35
+ //#endregion
36
+ export { o as t };
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./SpicySkeleton-3pNqXUU-.js";
2
+ export { e as SpicySkeleton, e as default };