@nonsuch/component-library 0.7.0 → 0.7.2

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
@@ -224,6 +224,45 @@ All tokens use the `--ns-` prefix and support light/dark mode automatically. Cur
224
224
 
225
225
  Dark mode activates via `class="dark"`, `data-theme="dark"`, Quasar's `.q-dark`, or `prefers-color-scheme: dark`.
226
226
 
227
+ ### Breakpoints
228
+
229
+ The library ships Quasar-aligned breakpoint values and media-query helpers:
230
+
231
+ ```ts
232
+ import {
233
+ nsBreakpoints,
234
+ nsMediaUp,
235
+ nsMediaDown,
236
+ nsMediaOnly,
237
+ nsMediaBetween,
238
+ } from '@nonsuch/component-library'
239
+ ```
240
+
241
+ | Name | Min-width | Range | Note |
242
+ | ---- | --------- | -------------- | ----- |
243
+ | xs | 0 | 0 – 599 px | |
244
+ | sm | 600 | 600 – 1023 px | |
245
+ | md | 1024 | 1024 – 1439 px | |
246
+ | lg | 1440 | 1440 – 1919 px | |
247
+ | xl | 1920 | 1920 – 2559 px | |
248
+ | xxl | 2560 | 2560 – 3839 px | 1440p |
249
+ | xxxl | 3840 | 3840 px + | 4K |
250
+
251
+ Media-query helpers return `matchMedia()`-ready strings:
252
+
253
+ ```ts
254
+ nsMediaUp('md') // '(min-width: 1024px)'
255
+ nsMediaDown('md') // '(max-width: 1023px)'
256
+ nsMediaOnly('md') // '(min-width: 1024px) and (max-width: 1439px)'
257
+ nsMediaBetween('sm', 'lg') // '(min-width: 600px) and (max-width: 1919px)'
258
+ ```
259
+
260
+ To customize in the future, spread and override:
261
+
262
+ ```ts
263
+ const custom = { ...nsBreakpoints, lg: 1280 }
264
+ ```
265
+
227
266
  ## Development
228
267
 
229
268
  ```bash
@@ -249,29 +288,67 @@ pnpm build:storybook
249
288
  ```text
250
289
  src/
251
290
  index.ts # Library entry — exports all public API
291
+ manifest.ts # Quasar → Ns component mapping for sync enforcement
252
292
  plugin.ts # createNonsuch() Vue plugin
253
293
  quasarConfig.ts # createQuasarConfig() helper
254
294
  components/
255
295
  NsAvatar/ # Avatar with size presets
296
+ NsBadge/ # Styled QBadge wrapper
256
297
  NsBanner/ # Info/success/warning/error banners
298
+ NsBreadcrumbs/ # Breadcrumb navigation
299
+ NsBreadcrumbElement/ # Individual breadcrumb item
257
300
  NsButton/ # Styled QBtn wrapper
301
+ NsButtonToggle/ # Toggle between button options
258
302
  NsCard/ # Card with title/subtitle/actions slots
303
+ NsCardActions/ # Card action bar
304
+ NsCardSection/ # Card content section
259
305
  NsCheckbox/ # Styled QCheckbox wrapper
260
306
  NsChip/ # Tag/filter chip
261
307
  NsDialog/ # Modal dialog with header/body/actions
308
+ NsDrawer/ # Side drawer (within NsLayout)
309
+ NsExpansionItem/ # Collapsible list item
310
+ NsFooter/ # App footer (within NsLayout)
262
311
  NsForm/ # Form wrapper with validation
312
+ NsHeader/ # App header (within NsLayout)
313
+ NsIcon/ # Styled QIcon wrapper
314
+ NsImage/ # Styled QImg wrapper
315
+ NsInnerLoading/ # Overlay loading indicator
263
316
  NsInput/ # Styled QInput wrapper
317
+ NsItem/ # List item
318
+ NsItemLabel/ # List item label
319
+ NsItemSection/ # List item section
320
+ NsLayout/ # App layout container
321
+ NsLinearProgress/ # Linear progress bar
264
322
  NsList/ # List with separator defaults
323
+ NsMenu/ # Dropdown/context menu
324
+ NsPage/ # Page content area
325
+ NsPageContainer/ # Page container (within NsLayout)
326
+ NsPagination/ # Page navigation controls
265
327
  NsSelect/ # Styled QSelect dropdown
328
+ NsSeparator/ # Horizontal/vertical separator
266
329
  NsSkeleton/ # Loading skeleton with animation
330
+ NsSpace/ # Flex spacer
331
+ NsSpinner/ # Circular spinner
332
+ NsSpinnerDots/ # Dot-style spinner
333
+ NsTab/ # Tab item (within NsTabs)
334
+ NsTabPanel/ # Tab panel content
335
+ NsTabPanels/ # Tab panels container
336
+ NsTable/ # Data table
337
+ NsTableCell/ # Table cell
338
+ NsTabs/ # Tab navigation bar
267
339
  NsThemeProvider/ # Renderless locale provider
340
+ NsTimeline/ # Timeline container
341
+ NsTimelineEntry/ # Timeline entry item
268
342
  NsToggle/ # Styled QToggle switch
343
+ NsToolbar/ # Toolbar container
344
+ NsToolbarTitle/ # Toolbar title
269
345
  NsTooltip/ # Tooltip with consistent delays
270
346
  composables/
271
347
  useNsLocale.ts # Locale injection/provision
272
348
  useNsDarkMode.ts # Dark mode with persistence
273
349
  useNsDefaults.ts # Default value helper
274
350
  locale/ # en-CA, fr-CA string packs
351
+ breakpoints/ # Breakpoint values + media query helpers
275
352
  tokens/ # Design token CSS + TS helpers
276
353
  fonts/ # Fixel font files + CSS
277
354
  ```
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Nonsuch Breakpoints
3
+ *
4
+ * Adopts Quasar's breakpoint scale as the library default.
5
+ * Values are customizable — update `nsBreakpoints` if Nonsuch
6
+ * needs to diverge from Quasar in the future.
7
+ *
8
+ * @see https://quasar.dev/style/breakpoints
9
+ */
10
+ /** Named breakpoint sizes. */
11
+ export type NsBreakpointName = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'xxxl';
12
+ /**
13
+ * Minimum widths (in pixels) for each breakpoint.
14
+ *
15
+ * | Name | Min-width | Range |
16
+ * |------|-----------|------------------|
17
+ * | xs | 0 | 0 – 599 px |
18
+ * | sm | 600 | 600 – 1023 px |
19
+ * | md | 1024 | 1024 – 1439 px |
20
+ * | lg | 1440 | 1440 – 1919 px |
21
+ * | xl | 1920 | 1920 – 2559 px |
22
+ * | xxl | 2560 | 2560 – 3839 px | (1440p)
23
+ * | xxxl | 3840 | 3840 px + | (4K)
24
+ *
25
+ * These match Quasar's defaults. To customize, spread and override:
26
+ * ```ts
27
+ * const custom = { ...nsBreakpoints, lg: 1280 }
28
+ * ```
29
+ */
30
+ export declare const nsBreakpoints: Record<NsBreakpointName, number>;
31
+ /** Ordered list of breakpoint names from smallest to largest. */
32
+ export declare const nsBreakpointNames: readonly NsBreakpointName[];
33
+ /**
34
+ * Generate a `min-width` media query string for the given breakpoint.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * nsMediaUp('md') // → '(min-width: 1024px)'
39
+ * ```
40
+ */
41
+ export declare function nsMediaUp(name: NsBreakpointName): string;
42
+ /**
43
+ * Generate a `max-width` media query string for the breakpoint
44
+ * immediately *below* the given one.
45
+ *
46
+ * Useful for targeting everything smaller than a breakpoint.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * nsMediaDown('md') // → '(max-width: 1023px)' — everything below md
51
+ * ```
52
+ */
53
+ export declare function nsMediaDown(name: Exclude<NsBreakpointName, 'xs'>): string;
54
+ /**
55
+ * Generate a media query string matching exactly one breakpoint range.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * nsMediaOnly('md') // → '(min-width: 1024px) and (max-width: 1439px)'
60
+ * nsMediaOnly('xl') // → '(min-width: 1920px)'
61
+ * ```
62
+ */
63
+ export declare function nsMediaOnly(name: NsBreakpointName): string;
64
+ /**
65
+ * Generate a media query for a range between two breakpoints (inclusive).
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * nsMediaBetween('sm', 'lg') // → '(min-width: 600px) and (max-width: 1919px)'
70
+ * ```
71
+ */
72
+ export declare function nsMediaBetween(from: NsBreakpointName, to: NsBreakpointName): string;
@@ -0,0 +1,15 @@
1
+ export interface NsDrawerProps {
2
+ }
3
+ declare var __VLS_8: {};
4
+ type __VLS_Slots = {} & {
5
+ default?: (props: typeof __VLS_8) => any;
6
+ };
7
+ declare const __VLS_base: import("vue").DefineComponent<NsDrawerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<NsDrawerProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
11
+ type __VLS_WithSlots<T, S> = T & {
12
+ new (): {
13
+ $slots: S;
14
+ };
15
+ };
@@ -0,0 +1 @@
1
+ export { default as NsDrawer } from './NsDrawer.vue';
@@ -0,0 +1,15 @@
1
+ export interface NsExpansionItemProps {
2
+ }
3
+ declare var __VLS_8: {};
4
+ type __VLS_Slots = {} & {
5
+ default?: (props: typeof __VLS_8) => any;
6
+ };
7
+ declare const __VLS_base: import("vue").DefineComponent<NsExpansionItemProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<NsExpansionItemProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
11
+ type __VLS_WithSlots<T, S> = T & {
12
+ new (): {
13
+ $slots: S;
14
+ };
15
+ };
@@ -0,0 +1 @@
1
+ export { default as NsExpansionItem } from './NsExpansionItem.vue';
package/dist/index.d.ts CHANGED
@@ -18,6 +18,10 @@ export { default as NsForm } from './components/NsForm/NsForm.vue';
18
18
  export type { NsFormProps } from './components/NsForm/NsForm.vue';
19
19
  export { default as NsDialog } from './components/NsDialog/NsDialog.vue';
20
20
  export type { NsDialogProps } from './components/NsDialog/NsDialog.vue';
21
+ export { default as NsDrawer } from './components/NsDrawer/NsDrawer.vue';
22
+ export type { NsDrawerProps } from './components/NsDrawer/NsDrawer.vue';
23
+ export { default as NsExpansionItem } from './components/NsExpansionItem/NsExpansionItem.vue';
24
+ export type { NsExpansionItemProps } from './components/NsExpansionItem/NsExpansionItem.vue';
21
25
  export { default as NsBanner } from './components/NsBanner/NsBanner.vue';
22
26
  export type { NsBannerProps, NsBannerType } from './components/NsBanner/NsBanner.vue';
23
27
  export { default as NsAvatar } from './components/NsAvatar/NsAvatar.vue';
@@ -109,4 +113,6 @@ export { useNsDarkMode } from './composables/useNsDarkMode';
109
113
  export type { UseNsDarkModeReturn } from './composables/useNsDarkMode';
110
114
  export type { NsToken } from './tokens';
111
115
  export { getToken } from './tokens';
116
+ export type { NsBreakpointName } from './breakpoints';
117
+ export { nsBreakpoints, nsBreakpointNames, nsMediaUp, nsMediaDown, nsMediaOnly, nsMediaBetween, } from './breakpoints';
112
118
  export { nsComponentManifest, nsTemplateTagManifest, generateQuasarBanRules } from './manifest';
@@ -1 +1 @@
1
- .ns-button[data-v-59b40e5f]{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-dfd40b8a]{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-7769879a]{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-7769879a]:hover{box-shadow:var(--ns-shadow-md)}.ns-card--flat[data-v-7769879a],.ns-card--flat[data-v-7769879a]:hover{box-shadow:none}.ns-card__header[data-v-7769879a]{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-f8c90530],.ns-form[data-v-e20d14ce]{font-family:var(--ns-font-family-text)}.ns-dialog__card[data-v-4fca48ca]{border-radius:var(--ns-radius-lg);font-family:var(--ns-font-family-text);min-width:320px}.ns-dialog__header[data-v-4fca48ca]{font-family:var(--ns-font-family-display)}.ns-banner[data-v-18ebd6f5]{font-family:var(--ns-font-family-text);border-radius:var(--ns-radius-md)}.ns-banner--info[data-v-18ebd6f5]{background-color:var(--ns-color-info-bg, #e3f2fd);color:var(--ns-color-info-text, #0d47a1)}.ns-banner--success[data-v-18ebd6f5]{background-color:var(--ns-color-success-bg, #e8f5e9);color:var(--ns-color-success-text, #1b5e20)}.ns-banner--warning[data-v-18ebd6f5]{background-color:var(--ns-color-warning-bg, #fff3e0);color:var(--ns-color-warning-text, #e65100)}.ns-banner--error[data-v-18ebd6f5]{background-color:var(--ns-color-error-bg, #ffebee);color:var(--ns-color-error-text, #b71c1c)}.ns-avatar[data-v-6a1b44b8]{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-65aec20e]{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)}.ns-badge[data-v-4ca05f24],.ns-breadcrumbs[data-v-dee98f71],.ns-breadcrumb-element[data-v-37bfe51b],.ns-button-toggle[data-v-93652c3e],.ns-card-actions[data-v-0d6f776d],.ns-card-section[data-v-781d42ef],.ns-footer[data-v-1fb919cd],.ns-header[data-v-80d27841],.ns-icon[data-v-d068ec18],.ns-image[data-v-c9c9f6c1],.ns-inner-loading[data-v-080672c1],.ns-item[data-v-47978f87],.ns-item-label[data-v-df6024af],.ns-item-section[data-v-340a753a],.ns-layout[data-v-cf90e270],.ns-linear-progress[data-v-79c6443f],.ns-menu[data-v-47a4b7d0],.ns-page[data-v-25e2841e],.ns-page-container[data-v-ac167da5],.ns-pagination[data-v-12fa9287],.ns-separator[data-v-0c2b2ac1],.ns-space[data-v-273ca5fc],.ns-spinner[data-v-5b99a17b],.ns-spinner-dots[data-v-20a70106],.ns-tab[data-v-b97f2cd1],.ns-table[data-v-a45d30cf],.ns-table-cell[data-v-ca0da61b],.ns-tab-panel[data-v-d8f64358],.ns-tab-panels[data-v-dec8ab0f],.ns-tabs[data-v-81224e01],.ns-timeline[data-v-1bf558aa],.ns-timeline-entry[data-v-fa149ea0],.ns-toolbar[data-v-e26a45db],.ns-toolbar-title[data-v-42928844]{font-family:var(--ns-font-family-text)}
1
+ .ns-button[data-v-59b40e5f]{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-dfd40b8a]{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-7769879a]{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-7769879a]:hover{box-shadow:var(--ns-shadow-md)}.ns-card--flat[data-v-7769879a],.ns-card--flat[data-v-7769879a]:hover{box-shadow:none}.ns-card__header[data-v-7769879a]{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-f8c90530],.ns-form[data-v-e20d14ce]{font-family:var(--ns-font-family-text)}.ns-dialog__card[data-v-4fca48ca]{border-radius:var(--ns-radius-lg);font-family:var(--ns-font-family-text);min-width:320px}.ns-dialog__header[data-v-4fca48ca]{font-family:var(--ns-font-family-display)}.ns-drawer[data-v-66ca96b0],.ns-expansion-item[data-v-c07366a7]{font-family:var(--ns-font-family-text)}.ns-banner[data-v-18ebd6f5]{font-family:var(--ns-font-family-text);border-radius:var(--ns-radius-md)}.ns-banner--info[data-v-18ebd6f5]{background-color:var(--ns-color-info-bg, #e3f2fd);color:var(--ns-color-info-text, #0d47a1)}.ns-banner--success[data-v-18ebd6f5]{background-color:var(--ns-color-success-bg, #e8f5e9);color:var(--ns-color-success-text, #1b5e20)}.ns-banner--warning[data-v-18ebd6f5]{background-color:var(--ns-color-warning-bg, #fff3e0);color:var(--ns-color-warning-text, #e65100)}.ns-banner--error[data-v-18ebd6f5]{background-color:var(--ns-color-error-bg, #ffebee);color:var(--ns-color-error-text, #b71c1c)}.ns-avatar[data-v-6a1b44b8]{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-65aec20e]{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)}.ns-badge[data-v-4ca05f24],.ns-breadcrumbs[data-v-dee98f71],.ns-breadcrumb-element[data-v-37bfe51b],.ns-button-toggle[data-v-93652c3e],.ns-card-actions[data-v-0d6f776d],.ns-card-section[data-v-781d42ef],.ns-footer[data-v-1fb919cd],.ns-header[data-v-80d27841],.ns-icon[data-v-d068ec18],.ns-image[data-v-c9c9f6c1],.ns-inner-loading[data-v-080672c1],.ns-item[data-v-47978f87],.ns-item-label[data-v-df6024af],.ns-item-section[data-v-340a753a],.ns-layout[data-v-cf90e270],.ns-linear-progress[data-v-79c6443f],.ns-menu[data-v-47a4b7d0],.ns-page[data-v-25e2841e],.ns-page-container[data-v-ac167da5],.ns-pagination[data-v-12fa9287],.ns-separator[data-v-0c2b2ac1],.ns-space[data-v-273ca5fc],.ns-spinner[data-v-5b99a17b],.ns-spinner-dots[data-v-20a70106],.ns-tab[data-v-b97f2cd1],.ns-table[data-v-a45d30cf],.ns-table-cell[data-v-ca0da61b],.ns-tab-panel[data-v-d8f64358],.ns-tab-panels[data-v-dec8ab0f],.ns-tabs[data-v-81224e01],.ns-timeline[data-v-1bf558aa],.ns-timeline-entry[data-v-fa149ea0],.ns-toolbar[data-v-e26a45db],.ns-toolbar-title[data-v-42928844]{font-family:var(--ns-font-family-text)}