@nonsuch/component-library 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,8 +35,8 @@ import '@nonsuch/component-library/tokens.css'
35
35
  import 'quasar/src/css/index.sass'
36
36
 
37
37
  const app = createApp(App)
38
- app.use(Quasar, createQuasarConfig()) // Token-aligned Quasar brand colours
39
- app.use(createNonsuch()) // Locale + library setup
38
+ app.use(Quasar, createQuasarConfig()) // Token-aligned Quasar brand colours
39
+ app.use(createNonsuch()) // Locale + library setup
40
40
  app.mount('#app')
41
41
  ```
42
42
 
@@ -74,10 +74,13 @@ app.use(createNonsuch({ locale: nsLocaleFrCA }))
74
74
  ```ts
75
75
  import { createQuasarConfig } from '@nonsuch/component-library'
76
76
 
77
- app.use(Quasar, createQuasarConfig({
78
- brand: { primary: '#1a73e8' },
79
- plugins: { Notify: {} },
80
- }))
77
+ app.use(
78
+ Quasar,
79
+ createQuasarConfig({
80
+ brand: { primary: '#1a73e8' },
81
+ plugins: { Notify: {} },
82
+ }),
83
+ )
81
84
  ```
82
85
 
83
86
  ### Dark Mode
@@ -243,24 +246,34 @@ pnpm build:storybook
243
246
 
244
247
  ## Project Structure
245
248
 
246
- ```markdown
249
+ ```text
247
250
  src/
248
- index.ts # Library entry — exports all public API
249
- plugin.ts # createNonsuch() Vue plugin
250
- quasarConfig.ts # createQuasarConfig() helper
251
+ index.ts # Library entry — exports all public API
252
+ plugin.ts # createNonsuch() Vue plugin
253
+ quasarConfig.ts # createQuasarConfig() helper
251
254
  components/
252
- NsButton/ # Styled QBtn wrapper
253
- NsCard/ # Card with title/subtitle/actions slots
254
- NsInput/ # Styled QInput wrapper
255
- NsSkeleton/ # Loading skeleton with animation
256
- NsThemeProvider/ # Renderless locale provider
255
+ NsAvatar/ # Avatar with size presets
256
+ NsBanner/ # Info/success/warning/error banners
257
+ NsButton/ # Styled QBtn wrapper
258
+ NsCard/ # Card with title/subtitle/actions slots
259
+ NsCheckbox/ # Styled QCheckbox wrapper
260
+ NsChip/ # Tag/filter chip
261
+ NsDialog/ # Modal dialog with header/body/actions
262
+ NsForm/ # Form wrapper with validation
263
+ NsInput/ # Styled QInput wrapper
264
+ NsList/ # List with separator defaults
265
+ NsSelect/ # Styled QSelect dropdown
266
+ NsSkeleton/ # Loading skeleton with animation
267
+ NsThemeProvider/ # Renderless locale provider
268
+ NsToggle/ # Styled QToggle switch
269
+ NsTooltip/ # Tooltip with consistent delays
257
270
  composables/
258
- useNsLocale.ts # Locale injection/provision
259
- useNsDarkMode.ts # Dark mode with persistence
260
- useNsDefaults.ts # Default value helper
261
- locale/ # en-CA, fr-CA string packs
262
- tokens/ # Design token CSS + TS helpers
263
- fonts/ # Fixel font files + CSS
271
+ useNsLocale.ts # Locale injection/provision
272
+ useNsDarkMode.ts # Dark mode with persistence
273
+ useNsDefaults.ts # Default value helper
274
+ locale/ # en-CA, fr-CA string packs
275
+ tokens/ # Design token CSS + TS helpers
276
+ fonts/ # Fixel font files + CSS
264
277
  ```
265
278
 
266
279
  Each custom component lives in its own directory with co-located story and test files. The `Ns` prefix distinguishes library components from Quasar's `Q` prefix.
@@ -1 +1 @@
1
- .ns-button[data-v-7f6c2760]{font-family:var(--ns-font-family-text);font-weight:var(--ns-font-weight-medium);letter-spacing:var(--ns-letter-spacing-wide)}.ns-skeleton[data-v-62627927]{border-radius:var(--ns-radius-md)}.ns-input[data-v-7ebf3284],.ns-input[data-v-7ebf3284] .q-field__label{font-family:var(--ns-font-family-text)}.ns-input[data-v-7ebf3284] .q-field__control{border-radius:var(--ns-radius-md)}.ns-card[data-v-41ecea50]{border-radius:var(--ns-radius-lg);box-shadow:var(--ns-shadow-sm);font-family:var(--ns-font-family-text);transition:box-shadow var(--ns-duration-normal) var(--ns-easing-default)}.ns-card[data-v-41ecea50]:hover{box-shadow:var(--ns-shadow-md)}.ns-card--flat[data-v-41ecea50],.ns-card--flat[data-v-41ecea50]:hover{box-shadow:none}.ns-card__header[data-v-41ecea50]{font-family:var(--ns-font-family-display)}
1
+ .ns-button[data-v-7f6c2760]{font-family:var(--ns-font-family-text);font-weight:var(--ns-font-weight-medium);letter-spacing:var(--ns-letter-spacing-wide)}.ns-skeleton[data-v-62627927]{border-radius:var(--ns-radius-md)}.ns-input[data-v-7ebf3284],.ns-input[data-v-7ebf3284] .q-field__label{font-family:var(--ns-font-family-text)}.ns-input[data-v-7ebf3284] .q-field__control{border-radius:var(--ns-radius-md)}.ns-card[data-v-41ecea50]{border-radius:var(--ns-radius-lg);box-shadow:var(--ns-shadow-sm);font-family:var(--ns-font-family-text);transition:box-shadow var(--ns-duration-normal) var(--ns-easing-default)}.ns-card[data-v-41ecea50]:hover{box-shadow:var(--ns-shadow-md)}.ns-card--flat[data-v-41ecea50],.ns-card--flat[data-v-41ecea50]:hover{box-shadow:none}.ns-card__header[data-v-41ecea50]{font-family:var(--ns-font-family-display)}.ns-select[data-v-081cebe3],.ns-select[data-v-081cebe3] .q-field__label{font-family:var(--ns-font-family-text)}.ns-select[data-v-081cebe3] .q-field__control{border-radius:var(--ns-radius-md)}.ns-checkbox[data-v-2e481f8b],.ns-toggle[data-v-beb96bf2],.ns-form[data-v-0fd74bb1]{font-family:var(--ns-font-family-text)}.ns-dialog__card[data-v-9bff0f12]{border-radius:var(--ns-radius-lg);font-family:var(--ns-font-family-text);min-width:320px}.ns-dialog__header[data-v-9bff0f12]{font-family:var(--ns-font-family-display)}.ns-banner[data-v-35ed7ae7]{font-family:var(--ns-font-family-text);border-radius:var(--ns-radius-md)}.ns-banner--info[data-v-35ed7ae7]{background-color:var(--ns-color-info-bg, #e3f2fd);color:var(--ns-color-info-text, #0d47a1)}.ns-banner--success[data-v-35ed7ae7]{background-color:var(--ns-color-success-bg, #e8f5e9);color:var(--ns-color-success-text, #1b5e20)}.ns-banner--warning[data-v-35ed7ae7]{background-color:var(--ns-color-warning-bg, #fff3e0);color:var(--ns-color-warning-text, #e65100)}.ns-banner--error[data-v-35ed7ae7]{background-color:var(--ns-color-error-bg, #ffebee);color:var(--ns-color-error-text, #b71c1c)}.ns-avatar[data-v-e4df869f]{font-family:var(--ns-font-family-text);font-weight:var(--ns-font-weight-medium)}.ns-chip[data-v-1a2191f1]{font-family:var(--ns-font-family-text);border-radius:var(--ns-radius-full, 9999px)}.ns-list[data-v-b778ff3f]{font-family:var(--ns-font-family-text);border-radius:var(--ns-radius-md)}.ns-tooltip[data-v-9cb6af8f]{font-family:var(--ns-font-family-text);font-size:var(--ns-font-size-sm, .875rem);border-radius:var(--ns-radius-sm);padding:var(--ns-space-1, 4px) var(--ns-space-2, 8px)}
@@ -1,12 +1,22 @@
1
- import Q from "quasar/src/components/btn/QBtn.js";
2
- import { defineComponent as c, openBlock as s, createBlock as d, mergeProps as p, withCtx as u, renderSlot as i, createVNode as B, unref as T, provide as V, inject as q, createSlots as z, renderList as R, normalizeProps as D, guardReactiveProps as M, createElementVNode as O, toDisplayString as w, createElementBlock as F, createCommentVNode as v, computed as _, ref as C, onMounted as x, onUnmounted as j, readonly as I } from "vue";
3
- import K from "quasar/src/components/spinner/QSpinnerDots.js";
4
- import U from "quasar/src/components/skeleton/QSkeleton.js";
5
- import Z from "quasar/src/components/input/QInput.js";
6
- import $ from "quasar/src/components/card/QCardSection.js";
7
- import G from "quasar/src/components/card/QCardActions.js";
8
- import H from "quasar/src/components/card/QCard.js";
9
- const Y = /* @__PURE__ */ c({
1
+ import M from "quasar/src/components/btn/QBtn.js";
2
+ import { defineComponent as u, openBlock as n, createBlock as d, mergeProps as i, withCtx as l, renderSlot as r, createVNode as g, unref as F, provide as U, inject as j, createSlots as k, renderList as Q, normalizeProps as E, guardReactiveProps as z, createElementVNode as L, toDisplayString as $, createElementBlock as K, createCommentVNode as p, computed as T, ref as I, onMounted as Z, onUnmounted as G, readonly as w } from "vue";
3
+ import H from "quasar/src/components/spinner/QSpinnerDots.js";
4
+ import Y from "quasar/src/components/skeleton/QSkeleton.js";
5
+ import J from "quasar/src/components/input/QInput.js";
6
+ import b from "quasar/src/components/card/QCardSection.js";
7
+ import A from "quasar/src/components/card/QCardActions.js";
8
+ import q from "quasar/src/components/card/QCard.js";
9
+ import W from "quasar/src/components/select/QSelect.js";
10
+ import X from "quasar/src/components/checkbox/QCheckbox.js";
11
+ import x from "quasar/src/components/toggle/QToggle.js";
12
+ import _ from "quasar/src/components/form/QForm.js";
13
+ import ee from "quasar/src/components/dialog/QDialog.js";
14
+ import te from "quasar/src/components/banner/QBanner.js";
15
+ import oe from "quasar/src/components/avatar/QAvatar.js";
16
+ import ae from "quasar/src/components/chip/QChip.js";
17
+ import le from "quasar/src/components/item/QList.js";
18
+ import se from "quasar/src/components/tooltip/QTooltip.js";
19
+ const ne = /* @__PURE__ */ u({
10
20
  __name: "NsButton",
11
21
  props: {
12
22
  color: { default: "primary" },
@@ -17,7 +27,7 @@ const Y = /* @__PURE__ */ c({
17
27
  loading: { type: Boolean, default: !1 }
18
28
  },
19
29
  setup(e) {
20
- return (t, o) => (s(), d(Q, p(t.$attrs, {
30
+ return (t, o) => (n(), d(M, i(t.$attrs, {
21
31
  color: e.color,
22
32
  size: e.size,
23
33
  unelevated: e.unelevated,
@@ -26,23 +36,23 @@ const Y = /* @__PURE__ */ c({
26
36
  loading: e.loading,
27
37
  class: "ns-button"
28
38
  }), {
29
- loading: u(() => [
30
- i(t.$slots, "loading", {}, () => [
31
- B(T(K), { color: "white" })
39
+ loading: l(() => [
40
+ r(t.$slots, "loading", {}, () => [
41
+ g(F(H), { color: "white" })
32
42
  ], !0)
33
43
  ]),
34
- default: u(() => [
35
- i(t.$slots, "default", {}, void 0, !0)
44
+ default: l(() => [
45
+ r(t.$slots, "default", {}, void 0, !0)
36
46
  ]),
37
47
  _: 3
38
48
  }, 16, ["color", "size", "unelevated", "no-caps", "rounded", "loading"]));
39
49
  }
40
- }), g = (e, t) => {
50
+ }), f = (e, t) => {
41
51
  const o = e.__vccOpts || e;
42
- for (const [n, r] of t)
43
- o[n] = r;
52
+ for (const [a, s] of t)
53
+ o[a] = s;
44
54
  return o;
45
- }, me = /* @__PURE__ */ g(Y, [["__scopeId", "data-v-7f6c2760"]]), J = /* @__PURE__ */ c({
55
+ }, Ke = /* @__PURE__ */ f(ne, [["__scopeId", "data-v-7f6c2760"]]), re = /* @__PURE__ */ u({
46
56
  __name: "NsSkeleton",
47
57
  props: {
48
58
  type: { default: "rect" },
@@ -53,7 +63,7 @@ const Y = /* @__PURE__ */ c({
53
63
  height: { default: void 0 }
54
64
  },
55
65
  setup(e) {
56
- return (t, o) => (s(), d(U, p(t.$attrs, {
66
+ return (t, o) => (n(), d(Y, i(t.$attrs, {
57
67
  type: e.type,
58
68
  animation: e.animation,
59
69
  square: e.square,
@@ -63,7 +73,7 @@ const Y = /* @__PURE__ */ c({
63
73
  class: "ns-skeleton"
64
74
  }), null, 16, ["type", "animation", "square", "bordered", "width", "height"]));
65
75
  }
66
- }), pe = /* @__PURE__ */ g(J, [["__scopeId", "data-v-62627927"]]), y = {
76
+ }), Ze = /* @__PURE__ */ f(re, [["__scopeId", "data-v-62627927"]]), B = {
67
77
  common: {
68
78
  loading: "Loading…",
69
79
  retry: "Retry",
@@ -99,22 +109,22 @@ const Y = /* @__PURE__ */ c({
99
109
  tooShort: "Too short",
100
110
  tooLong: "Too long"
101
111
  }
102
- }, S = /* @__PURE__ */ Symbol("ns-locale");
103
- function W(e) {
104
- V(S, e);
112
+ }, N = /* @__PURE__ */ Symbol("ns-locale");
113
+ function de(e) {
114
+ U(N, e);
105
115
  }
106
- function X() {
107
- return q(S, y);
116
+ function ue() {
117
+ return j(N, B);
108
118
  }
109
- const ge = /* @__PURE__ */ c({
119
+ const Ge = /* @__PURE__ */ u({
110
120
  __name: "NsThemeProvider",
111
121
  props: {
112
- locale: { default: () => y }
122
+ locale: { default: () => B }
113
123
  },
114
124
  setup(e) {
115
- return W(e.locale), (o, n) => i(o.$slots, "default");
125
+ return de(e.locale), (o, a) => r(o.$slots, "default");
116
126
  }
117
- }), ee = /* @__PURE__ */ c({
127
+ }), ie = /* @__PURE__ */ u({
118
128
  __name: "NsInput",
119
129
  props: {
120
130
  label: { default: void 0 },
@@ -125,27 +135,27 @@ const ge = /* @__PURE__ */ c({
125
135
  },
126
136
  emits: ["update:modelValue"],
127
137
  setup(e) {
128
- return (t, o) => (s(), d(Z, p(t.$attrs, {
138
+ return (t, o) => (n(), d(J, i(t.$attrs, {
129
139
  "model-value": e.modelValue,
130
140
  label: e.label,
131
141
  outlined: e.outlined,
132
142
  dense: e.dense,
133
143
  rules: e.rules,
134
144
  class: "ns-input",
135
- "onUpdate:modelValue": o[0] || (o[0] = (n) => t.$emit("update:modelValue", n))
136
- }), z({ _: 2 }, [
137
- R(t.$slots, (n, r) => ({
138
- name: r,
139
- fn: u((l) => [
140
- i(t.$slots, r, D(M(l ?? {})), void 0, !0)
145
+ "onUpdate:modelValue": o[0] || (o[0] = (a) => t.$emit("update:modelValue", a))
146
+ }), k({ _: 2 }, [
147
+ Q(t.$slots, (a, s) => ({
148
+ name: s,
149
+ fn: l((c) => [
150
+ r(t.$slots, s, E(z(c ?? {})), void 0, !0)
141
151
  ])
142
152
  }))
143
153
  ]), 1040, ["model-value", "label", "outlined", "dense", "rules"]));
144
154
  }
145
- }), ve = /* @__PURE__ */ g(ee, [["__scopeId", "data-v-7ebf3284"]]), te = { class: "text-h6" }, oe = {
155
+ }), He = /* @__PURE__ */ f(ie, [["__scopeId", "data-v-7ebf3284"]]), fe = { class: "text-h6" }, ce = {
146
156
  key: 0,
147
157
  class: "text-subtitle2 text-grey"
148
- }, ne = /* @__PURE__ */ c({
158
+ }, me = /* @__PURE__ */ u({
149
159
  __name: "NsCard",
150
160
  props: {
151
161
  title: { default: void 0 },
@@ -153,51 +163,336 @@ const ge = /* @__PURE__ */ c({
153
163
  flat: { type: Boolean, default: !1 }
154
164
  },
155
165
  setup(e) {
156
- return (t, o) => (s(), d(H, p(t.$attrs, {
166
+ return (t, o) => (n(), d(q, i(t.$attrs, {
157
167
  class: ["ns-card", { "ns-card--flat": e.flat }]
158
168
  }), {
159
- default: u(() => [
160
- e.title || t.$slots.header ? (s(), d($, {
169
+ default: l(() => [
170
+ e.title || t.$slots.header ? (n(), d(b, {
161
171
  key: 0,
162
172
  class: "ns-card__header"
163
173
  }, {
164
- default: u(() => [
165
- i(t.$slots, "header", {}, () => [
166
- O("div", te, w(e.title), 1),
167
- e.subtitle ? (s(), F("div", oe, w(e.subtitle), 1)) : v("", !0)
174
+ default: l(() => [
175
+ r(t.$slots, "header", {}, () => [
176
+ L("div", fe, $(e.title), 1),
177
+ e.subtitle ? (n(), K("div", ce, $(e.subtitle), 1)) : p("", !0)
168
178
  ], !0)
169
179
  ]),
170
180
  _: 3
171
- })) : v("", !0),
172
- B($, null, {
173
- default: u(() => [
174
- i(t.$slots, "default", {}, void 0, !0)
181
+ })) : p("", !0),
182
+ g(b, null, {
183
+ default: l(() => [
184
+ r(t.$slots, "default", {}, void 0, !0)
175
185
  ]),
176
186
  _: 3
177
187
  }),
178
- t.$slots.actions ? (s(), d(G, {
188
+ t.$slots.actions ? (n(), d(A, {
179
189
  key: 1,
180
190
  align: "right"
181
191
  }, {
182
- default: u(() => [
183
- i(t.$slots, "actions", {}, void 0, !0)
192
+ default: l(() => [
193
+ r(t.$slots, "actions", {}, void 0, !0)
184
194
  ]),
185
195
  _: 3
186
- })) : v("", !0)
196
+ })) : p("", !0)
187
197
  ]),
188
198
  _: 3
189
199
  }, 16, ["class"]));
190
200
  }
191
- }), he = /* @__PURE__ */ g(ne, [["__scopeId", "data-v-41ecea50"]]);
192
- function ye(e = {}) {
193
- const { locale: t = y } = e;
201
+ }), Ye = /* @__PURE__ */ f(me, [["__scopeId", "data-v-41ecea50"]]), pe = /* @__PURE__ */ u({
202
+ __name: "NsSelect",
203
+ props: {
204
+ label: { default: void 0 },
205
+ modelValue: { default: void 0 },
206
+ options: { default: () => [] },
207
+ outlined: { type: Boolean, default: !0 },
208
+ dense: { type: Boolean, default: !1 },
209
+ multiple: { type: Boolean, default: !1 },
210
+ emitValue: { type: Boolean, default: !1 },
211
+ mapOptions: { type: Boolean, default: !1 },
212
+ rules: { default: void 0 }
213
+ },
214
+ emits: ["update:modelValue"],
215
+ setup(e) {
216
+ return (t, o) => (n(), d(W, i(t.$attrs, {
217
+ "model-value": e.modelValue,
218
+ label: e.label,
219
+ options: e.options,
220
+ outlined: e.outlined,
221
+ dense: e.dense,
222
+ rules: e.rules,
223
+ multiple: e.multiple,
224
+ "emit-value": e.emitValue,
225
+ "map-options": e.mapOptions,
226
+ class: "ns-select",
227
+ "onUpdate:modelValue": o[0] || (o[0] = (a) => t.$emit("update:modelValue", a))
228
+ }), k({ _: 2 }, [
229
+ Q(t.$slots, (a, s) => ({
230
+ name: s,
231
+ fn: l((c) => [
232
+ r(t.$slots, s, E(z(c ?? {})), void 0, !0)
233
+ ])
234
+ }))
235
+ ]), 1040, ["model-value", "label", "options", "outlined", "dense", "rules", "multiple", "emit-value", "map-options"]));
236
+ }
237
+ }), Je = /* @__PURE__ */ f(pe, [["__scopeId", "data-v-081cebe3"]]), ve = /* @__PURE__ */ u({
238
+ __name: "NsCheckbox",
239
+ props: {
240
+ label: { default: void 0 },
241
+ modelValue: { type: Boolean, default: !1 },
242
+ color: { default: "primary" },
243
+ dense: { type: Boolean, default: !1 },
244
+ disable: { type: Boolean, default: !1 }
245
+ },
246
+ emits: ["update:modelValue"],
247
+ setup(e) {
248
+ return (t, o) => (n(), d(X, i(t.$attrs, {
249
+ "model-value": e.modelValue,
250
+ label: e.label,
251
+ color: e.color,
252
+ dense: e.dense,
253
+ disable: e.disable,
254
+ class: "ns-checkbox",
255
+ "onUpdate:modelValue": o[0] || (o[0] = (a) => t.$emit("update:modelValue", a))
256
+ }), null, 16, ["model-value", "label", "color", "dense", "disable"]));
257
+ }
258
+ }), We = /* @__PURE__ */ f(ve, [["__scopeId", "data-v-2e481f8b"]]), ye = /* @__PURE__ */ u({
259
+ __name: "NsToggle",
260
+ props: {
261
+ label: { default: void 0 },
262
+ modelValue: { type: Boolean, default: !1 },
263
+ color: { default: "primary" },
264
+ dense: { type: Boolean, default: !1 },
265
+ disable: { type: Boolean, default: !1 }
266
+ },
267
+ emits: ["update:modelValue"],
268
+ setup(e) {
269
+ return (t, o) => (n(), d(x, i(t.$attrs, {
270
+ "model-value": e.modelValue,
271
+ label: e.label,
272
+ color: e.color,
273
+ dense: e.dense,
274
+ disable: e.disable,
275
+ class: "ns-toggle",
276
+ "onUpdate:modelValue": o[0] || (o[0] = (a) => t.$emit("update:modelValue", a))
277
+ }), null, 16, ["model-value", "label", "color", "dense", "disable"]));
278
+ }
279
+ }), Xe = /* @__PURE__ */ f(ye, [["__scopeId", "data-v-beb96bf2"]]), ge = /* @__PURE__ */ u({
280
+ __name: "NsForm",
281
+ props: {
282
+ greedy: { type: Boolean, default: !0 }
283
+ },
284
+ emits: ["submit", "validationError"],
285
+ setup(e) {
286
+ return (t, o) => (n(), d(_, i(t.$attrs, {
287
+ class: "ns-form",
288
+ greedy: e.greedy,
289
+ onSubmit: o[0] || (o[0] = (a) => t.$emit("submit", a)),
290
+ onValidationError: o[1] || (o[1] = (a) => t.$emit("validationError", a))
291
+ }), {
292
+ default: l(() => [
293
+ r(t.$slots, "default", {}, void 0, !0)
294
+ ]),
295
+ _: 3
296
+ }, 16, ["greedy"]));
297
+ }
298
+ }), xe = /* @__PURE__ */ f(ge, [["__scopeId", "data-v-0fd74bb1"]]), be = { class: "text-h6" }, he = /* @__PURE__ */ u({
299
+ __name: "NsDialog",
300
+ props: {
301
+ modelValue: { type: Boolean, default: !1 },
302
+ title: { default: void 0 },
303
+ persistent: { type: Boolean, default: !1 },
304
+ noBackdropDismiss: { type: Boolean, default: !1 }
305
+ },
306
+ emits: ["update:modelValue"],
307
+ setup(e) {
308
+ return (t, o) => (n(), d(ee, i(t.$attrs, {
309
+ "model-value": e.modelValue,
310
+ persistent: e.persistent,
311
+ "no-backdrop-dismiss": e.noBackdropDismiss,
312
+ class: "ns-dialog",
313
+ "onUpdate:modelValue": o[0] || (o[0] = (a) => t.$emit("update:modelValue", a))
314
+ }), {
315
+ default: l(() => [
316
+ g(q, { class: "ns-dialog__card" }, {
317
+ default: l(() => [
318
+ e.title || t.$slots.header ? (n(), d(b, {
319
+ key: 0,
320
+ class: "ns-dialog__header"
321
+ }, {
322
+ default: l(() => [
323
+ r(t.$slots, "header", {}, () => [
324
+ L("div", be, $(e.title), 1)
325
+ ], !0)
326
+ ]),
327
+ _: 3
328
+ })) : p("", !0),
329
+ g(b, { class: "ns-dialog__body" }, {
330
+ default: l(() => [
331
+ r(t.$slots, "default", {}, void 0, !0)
332
+ ]),
333
+ _: 3
334
+ }),
335
+ t.$slots.actions ? (n(), d(A, {
336
+ key: 1,
337
+ align: "right",
338
+ class: "ns-dialog__actions"
339
+ }, {
340
+ default: l(() => [
341
+ r(t.$slots, "actions", {}, void 0, !0)
342
+ ]),
343
+ _: 3
344
+ })) : p("", !0)
345
+ ]),
346
+ _: 3
347
+ })
348
+ ]),
349
+ _: 3
350
+ }, 16, ["model-value", "persistent", "no-backdrop-dismiss"]));
351
+ }
352
+ }), _e = /* @__PURE__ */ f(he, [["__scopeId", "data-v-9bff0f12"]]), $e = /* @__PURE__ */ u({
353
+ __name: "NsBanner",
354
+ props: {
355
+ type: { default: "info" },
356
+ dense: { type: Boolean, default: !1 },
357
+ rounded: { type: Boolean, default: !0 }
358
+ },
359
+ setup(e) {
360
+ return (t, o) => (n(), d(te, i(t.$attrs, {
361
+ class: ["ns-banner", `ns-banner--${e.type}`],
362
+ dense: e.dense,
363
+ rounded: e.rounded
364
+ }), k({
365
+ default: l(() => [
366
+ r(t.$slots, "default", {}, void 0, !0)
367
+ ]),
368
+ _: 2
369
+ }, [
370
+ t.$slots.avatar ? {
371
+ name: "avatar",
372
+ fn: l(() => [
373
+ r(t.$slots, "avatar", {}, void 0, !0)
374
+ ]),
375
+ key: "0"
376
+ } : void 0,
377
+ t.$slots.action ? {
378
+ name: "action",
379
+ fn: l(() => [
380
+ r(t.$slots, "action", {}, void 0, !0)
381
+ ]),
382
+ key: "1"
383
+ } : void 0
384
+ ]), 1040, ["class", "dense", "rounded"]));
385
+ }
386
+ }), et = /* @__PURE__ */ f($e, [["__scopeId", "data-v-35ed7ae7"]]), ke = /* @__PURE__ */ u({
387
+ __name: "NsAvatar",
388
+ props: {
389
+ size: { default: "md" },
390
+ color: { default: "primary" },
391
+ textColor: { default: "white" },
392
+ rounded: { type: Boolean, default: !1 },
393
+ square: { type: Boolean, default: !1 }
394
+ },
395
+ setup(e) {
396
+ const t = {
397
+ sm: "32px",
398
+ md: "48px",
399
+ lg: "64px",
400
+ xl: "96px"
401
+ }, o = e, a = T(() => t[o.size] ?? o.size);
402
+ return (s, c) => (n(), d(oe, i(s.$attrs, {
403
+ size: a.value,
404
+ color: e.color,
405
+ "text-color": e.textColor,
406
+ rounded: e.rounded,
407
+ square: e.square,
408
+ class: "ns-avatar"
409
+ }), {
410
+ default: l(() => [
411
+ r(s.$slots, "default", {}, void 0, !0)
412
+ ]),
413
+ _: 3
414
+ }, 16, ["size", "color", "text-color", "rounded", "square"]));
415
+ }
416
+ }), tt = /* @__PURE__ */ f(ke, [["__scopeId", "data-v-e4df869f"]]), Be = /* @__PURE__ */ u({
417
+ __name: "NsChip",
418
+ props: {
419
+ color: { default: "primary" },
420
+ textColor: { default: "white" },
421
+ outline: { type: Boolean, default: !1 },
422
+ dense: { type: Boolean, default: !1 },
423
+ removable: { type: Boolean, default: !1 },
424
+ clickable: { type: Boolean, default: !1 }
425
+ },
426
+ emits: ["remove"],
427
+ setup(e) {
428
+ return (t, o) => (n(), d(ae, i(t.$attrs, {
429
+ color: e.color,
430
+ "text-color": e.textColor,
431
+ outline: e.outline,
432
+ dense: e.dense,
433
+ removable: e.removable,
434
+ clickable: e.clickable,
435
+ class: "ns-chip",
436
+ onRemove: o[0] || (o[0] = (a) => t.$emit("remove"))
437
+ }), {
438
+ default: l(() => [
439
+ r(t.$slots, "default", {}, void 0, !0)
440
+ ]),
441
+ _: 3
442
+ }, 16, ["color", "text-color", "outline", "dense", "removable", "clickable"]));
443
+ }
444
+ }), ot = /* @__PURE__ */ f(Be, [["__scopeId", "data-v-1a2191f1"]]), Ne = /* @__PURE__ */ u({
445
+ __name: "NsList",
446
+ props: {
447
+ bordered: { type: Boolean, default: !1 },
448
+ separator: { type: Boolean, default: !0 },
449
+ dense: { type: Boolean, default: !1 }
450
+ },
451
+ setup(e) {
452
+ return (t, o) => (n(), d(le, i(t.$attrs, {
453
+ bordered: e.bordered,
454
+ separator: e.separator,
455
+ dense: e.dense,
456
+ class: "ns-list"
457
+ }), {
458
+ default: l(() => [
459
+ r(t.$slots, "default", {}, void 0, !0)
460
+ ]),
461
+ _: 3
462
+ }, 16, ["bordered", "separator", "dense"]));
463
+ }
464
+ }), at = /* @__PURE__ */ f(Ne, [["__scopeId", "data-v-b778ff3f"]]), Se = /* @__PURE__ */ u({
465
+ __name: "NsTooltip",
466
+ props: {
467
+ delay: { default: 300 },
468
+ offset: { default: () => [8, 0] },
469
+ anchor: { default: "bottom middle" },
470
+ self: { default: "top middle" }
471
+ },
472
+ setup(e) {
473
+ return (t, o) => (n(), d(se, i(t.$attrs, {
474
+ delay: e.delay,
475
+ offset: e.offset,
476
+ anchor: e.anchor,
477
+ self: e.self,
478
+ class: "ns-tooltip"
479
+ }), {
480
+ default: l(() => [
481
+ r(t.$slots, "default", {}, void 0, !0)
482
+ ]),
483
+ _: 3
484
+ }, 16, ["delay", "offset", "anchor", "self"]));
485
+ }
486
+ }), lt = /* @__PURE__ */ f(Se, [["__scopeId", "data-v-9cb6af8f"]]);
487
+ function st(e = {}) {
488
+ const { locale: t = B } = e;
194
489
  return {
195
490
  install(o) {
196
- o.provide(S, t);
491
+ o.provide(N, t);
197
492
  }
198
493
  };
199
494
  }
200
- const re = {
495
+ const Ve = {
201
496
  primary: "#3b82f6",
202
497
  // PLACEHOLDER — matches --ns-color-primary
203
498
  secondary: "#8b5cf6",
@@ -217,20 +512,20 @@ const re = {
217
512
  warning: "#f59e0b"
218
513
  // PLACEHOLDER — matches --ns-color-warning
219
514
  };
220
- function Se(e = {}) {
221
- const { brand: t = {}, plugins: o = {}, ...n } = e;
515
+ function nt(e = {}) {
516
+ const { brand: t = {}, plugins: o = {}, ...a } = e;
222
517
  return {
223
518
  config: {
224
519
  brand: {
225
- ...re,
520
+ ...Ve,
226
521
  ...t
227
522
  }
228
523
  },
229
524
  plugins: o,
230
- ...n
525
+ ...a
231
526
  };
232
527
  }
233
- const ke = {
528
+ const rt = {
234
529
  common: {
235
530
  loading: "Chargement…",
236
531
  retry: "Réessayer",
@@ -267,88 +562,98 @@ const ke = {
267
562
  tooLong: "Trop long"
268
563
  }
269
564
  };
270
- function be(e, t) {
271
- const o = X();
272
- return _(() => {
273
- const n = e();
274
- if (n != null) return n;
275
- const r = t.split(".");
276
- let l = o;
277
- for (const f of r)
278
- l = l[f];
279
- return l;
565
+ function dt(e, t) {
566
+ const o = ue();
567
+ return T(() => {
568
+ const a = e();
569
+ if (a != null) return a;
570
+ const s = t.split(".");
571
+ let c = o;
572
+ for (const v of s)
573
+ c = c[v];
574
+ return c;
280
575
  });
281
576
  }
282
577
  const h = "ns-dark-mode";
283
- function Ne() {
284
- const e = C(!1), t = C("system");
285
- let o = null, n = null;
286
- function r(a) {
287
- if (e.value = a, typeof document < "u") {
288
- const m = document.documentElement;
289
- m.classList.toggle("dark", a), m.setAttribute("data-theme", a ? "dark" : "light");
578
+ function ut() {
579
+ const e = I(!1), t = I("system");
580
+ let o = null, a = null;
581
+ function s(m) {
582
+ if (e.value = m, typeof document < "u") {
583
+ const y = document.documentElement;
584
+ y.classList.toggle("dark", m), y.setAttribute("data-theme", m ? "dark" : "light");
290
585
  }
291
586
  }
292
- function l() {
587
+ function c() {
293
588
  return typeof window > "u" ? !1 : window.matchMedia("(prefers-color-scheme: dark)").matches;
294
589
  }
295
- function f() {
590
+ function v() {
296
591
  if (typeof localStorage > "u") return null;
297
- const a = localStorage.getItem(h);
298
- return a === "true" ? !0 : a === "false" ? !1 : null;
592
+ const m = localStorage.getItem(h);
593
+ return m === "true" ? !0 : m === "false" ? !1 : null;
299
594
  }
300
- function k(a) {
301
- typeof localStorage < "u" && localStorage.setItem(h, String(a));
595
+ function S(m) {
596
+ typeof localStorage < "u" && localStorage.setItem(h, String(m));
302
597
  }
303
- function E() {
598
+ function D() {
304
599
  typeof localStorage < "u" && localStorage.removeItem(h);
305
600
  }
306
- function b() {
307
- t.value = "user", k(!0), r(!0);
601
+ function V() {
602
+ t.value = "user", S(!0), s(!0);
308
603
  }
309
- function N() {
310
- t.value = "user", k(!1), r(!1);
604
+ function C() {
605
+ t.value = "user", S(!1), s(!1);
311
606
  }
312
- function L() {
313
- e.value ? N() : b();
607
+ function P() {
608
+ e.value ? C() : V();
314
609
  }
315
- function A() {
316
- E(), t.value = "system", r(l());
610
+ function R() {
611
+ D(), t.value = "system", s(c());
317
612
  }
318
- function P() {
319
- const a = f();
320
- a !== null ? (t.value = "storage", r(a)) : (t.value = "system", r(l())), typeof window < "u" && (o = window.matchMedia("(prefers-color-scheme: dark)"), n = (m) => {
321
- f() === null && (t.value = "system", r(m.matches));
322
- }, o.addEventListener("change", n));
613
+ function O() {
614
+ const m = v();
615
+ m !== null ? (t.value = "storage", s(m)) : (t.value = "system", s(c())), typeof window < "u" && (o = window.matchMedia("(prefers-color-scheme: dark)"), a = (y) => {
616
+ v() === null && (t.value = "system", s(y.matches));
617
+ }, o.addEventListener("change", a));
323
618
  }
324
- return x(P), j(() => {
325
- o && n && o.removeEventListener("change", n);
619
+ return Z(O), G(() => {
620
+ o && a && o.removeEventListener("change", a);
326
621
  }), {
327
- isDark: I(e),
328
- source: I(t),
329
- enable: b,
330
- disable: N,
331
- toggle: L,
332
- useSystem: A
622
+ isDark: w(e),
623
+ source: w(t),
624
+ enable: V,
625
+ disable: C,
626
+ toggle: P,
627
+ useSystem: R
333
628
  };
334
629
  }
335
- function we(e, t = document.documentElement) {
630
+ function it(e, t = document.documentElement) {
336
631
  return getComputedStyle(t).getPropertyValue(e).trim();
337
632
  }
338
633
  export {
339
- me as NsButton,
340
- he as NsCard,
341
- ve as NsInput,
342
- S as NsLocaleKey,
343
- pe as NsSkeleton,
344
- ge as NsThemeProvider,
345
- ye as createNonsuch,
346
- Se as createQuasarConfig,
347
- we as getToken,
348
- y as nsLocaleEnCA,
349
- ke as nsLocaleFrCA,
350
- W as provideNsLocale,
351
- Ne as useNsDarkMode,
352
- be as useNsDefault,
353
- X as useNsLocale
634
+ tt as NsAvatar,
635
+ et as NsBanner,
636
+ Ke as NsButton,
637
+ Ye as NsCard,
638
+ We as NsCheckbox,
639
+ ot as NsChip,
640
+ _e as NsDialog,
641
+ xe as NsForm,
642
+ He as NsInput,
643
+ at as NsList,
644
+ N as NsLocaleKey,
645
+ Je as NsSelect,
646
+ Ze as NsSkeleton,
647
+ Ge as NsThemeProvider,
648
+ Xe as NsToggle,
649
+ lt as NsTooltip,
650
+ st as createNonsuch,
651
+ nt as createQuasarConfig,
652
+ it as getToken,
653
+ B as nsLocaleEnCA,
654
+ rt as nsLocaleFrCA,
655
+ de as provideNsLocale,
656
+ ut as useNsDarkMode,
657
+ dt as useNsDefault,
658
+ ue as useNsLocale
354
659
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nonsuch/component-library",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "A Vue 3 component library built on Quasar with opinionated defaults and custom components.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -41,7 +41,8 @@
41
41
  "test:watch": "vitest",
42
42
  "test:coverage": "vitest run --coverage",
43
43
  "preview": "vite preview",
44
- "prepublishOnly": "pnpm lint && pnpm typecheck && pnpm test && pnpm build"
44
+ "prepublishOnly": "pnpm lint && pnpm typecheck && pnpm test && pnpm build",
45
+ "prepare": "husky"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "@quasar/vite-plugin": "^1.8.0",
@@ -64,11 +65,14 @@
64
65
  "@quasar/vite-plugin": "^1.10.0",
65
66
  "@storybook/vue3-vite": "^10.2.7",
66
67
  "@vitejs/plugin-vue": "^6.0.4",
68
+ "@vitest/coverage-v8": "^4.0.18",
67
69
  "@vue/test-utils": "^2.4.6",
68
- "eslint": "^9.39.2",
70
+ "eslint": "^10.0.0",
69
71
  "eslint-config-prettier": "^10.1.8",
70
72
  "eslint-plugin-vue": "^10.7.0",
71
73
  "happy-dom": "^20.5.3",
74
+ "husky": "^9.1.7",
75
+ "lint-staged": "^16.2.7",
72
76
  "postcss-rtlcss": "^5.7.1",
73
77
  "prettier": "^3.8.1",
74
78
  "quasar": "^2.18.6",
@@ -81,5 +85,9 @@
81
85
  "vue": "^3.5.27",
82
86
  "vue-tsc": "^3.2.4"
83
87
  },
84
- "packageManager": "pnpm@10.29.2"
88
+ "packageManager": "pnpm@10.29.2",
89
+ "lint-staged": {
90
+ "*.{ts,vue}": "eslint --fix",
91
+ "*.{ts,vue,json,md,css,scss,sass,html,yaml,yml}": "prettier --write"
92
+ }
85
93
  }