@dorsk/tsumikit 0.35.1 → 0.37.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 (34) hide show
  1. package/README.md +26 -5
  2. package/dist/cap-bar.d.ts +8 -0
  3. package/dist/cap-bar.js +43 -0
  4. package/dist/components/atoms/Gauge.svelte +165 -0
  5. package/dist/components/atoms/Gauge.svelte.d.ts +24 -0
  6. package/dist/components/atoms/Select.svelte +112 -4
  7. package/dist/components/atoms/Select.svelte.d.ts +12 -0
  8. package/dist/components/layouts/MasterDetail.svelte +220 -0
  9. package/dist/components/layouts/MasterDetail.svelte.d.ts +22 -0
  10. package/dist/components/molecules/CapBar.svelte +254 -0
  11. package/dist/components/molecules/CapBar.svelte.d.ts +33 -0
  12. package/dist/components/molecules/Drawer.svelte +299 -0
  13. package/dist/components/molecules/Drawer.svelte.d.ts +35 -0
  14. package/dist/components/molecules/Fieldset.svelte +183 -0
  15. package/dist/components/molecules/Fieldset.svelte.d.ts +22 -0
  16. package/dist/components/molecules/GitRef.svelte +174 -0
  17. package/dist/components/molecules/GitRef.svelte.d.ts +30 -0
  18. package/dist/components/molecules/Menu.svelte +24 -1
  19. package/dist/components/molecules/Menu.svelte.d.ts +5 -0
  20. package/dist/components/molecules/RadioGroup.svelte +120 -14
  21. package/dist/components/molecules/RadioGroup.svelte.d.ts +6 -0
  22. package/dist/components/molecules/SectionHeader.svelte +35 -1
  23. package/dist/components/molecules/SectionHeader.svelte.d.ts +3 -0
  24. package/dist/components/molecules/Timestamp.svelte +7 -5
  25. package/dist/components/molecules/Timestamp.svelte.d.ts +2 -2
  26. package/dist/components/molecules/WorkingDir.svelte +134 -0
  27. package/dist/components/molecules/WorkingDir.svelte.d.ts +21 -0
  28. package/dist/index.d.ts +9 -0
  29. package/dist/index.js +8 -0
  30. package/dist/timestamp.d.ts +11 -5
  31. package/dist/timestamp.js +16 -2
  32. package/dist/working-dir.d.ts +12 -0
  33. package/dist/working-dir.js +38 -0
  34. package/package.json +10 -2
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ export { default as Button } from './components/atoms/Button.svelte';
13
13
  export { default as Card } from './components/atoms/Card.svelte';
14
14
  export { default as Checkbox } from './components/atoms/Checkbox.svelte';
15
15
  export { default as Dot } from './components/atoms/Dot.svelte';
16
+ export { default as Gauge } from './components/atoms/Gauge.svelte';
16
17
  export { default as Heading } from './components/atoms/Heading.svelte';
17
18
  export { default as Icon } from './components/atoms/Icon.svelte';
18
19
  export { default as Input } from './components/atoms/Input.svelte';
@@ -34,6 +35,7 @@ export { default as AppShell } from './components/layouts/AppShell.svelte';
34
35
  export { default as AutoGrid } from './components/layouts/AutoGrid.svelte';
35
36
  export { default as Cluster } from './components/layouts/Cluster.svelte';
36
37
  export { default as Container } from './components/layouts/Container.svelte';
38
+ export { default as MasterDetail } from './components/layouts/MasterDetail.svelte';
37
39
  export { default as NavItem } from './components/layouts/NavItem.svelte';
38
40
  export { default as NavSection } from './components/layouts/NavSection.svelte';
39
41
  export { default as ResizablePanel } from './components/layouts/ResizablePanel.svelte';
@@ -42,16 +44,20 @@ export { default as Stack } from './components/layouts/Stack.svelte';
42
44
  export { default as Accordion, } from './components/molecules/Accordion.svelte';
43
45
  export { default as Breadcrumb, } from './components/molecules/Breadcrumb.svelte';
44
46
  export { default as Callout } from './components/molecules/Callout.svelte';
47
+ export { default as CapBar } from './components/molecules/CapBar.svelte';
45
48
  export { default as CodeBlock } from './components/molecules/CodeBlock.svelte';
46
49
  export { default as ConfirmModal } from './components/molecules/ConfirmModal.svelte';
47
50
  export { default as CopyButton } from './components/molecules/CopyButton.svelte';
51
+ export { default as Drawer } from './components/molecules/Drawer.svelte';
48
52
  export { default as Dropzone } from './components/molecules/Dropzone.svelte';
49
53
  export { default as EmptyState } from './components/molecules/EmptyState.svelte';
50
54
  // ---- molecules ----
51
55
  export { default as Field } from './components/molecules/Field.svelte';
56
+ export { default as Fieldset } from './components/molecules/Fieldset.svelte';
52
57
  export { default as FileButton } from './components/molecules/FileButton.svelte';
53
58
  export { default as FilterInput, } from './components/molecules/FilterInput.svelte';
54
59
  export { default as FontScalePicker } from './components/molecules/FontScalePicker.svelte';
60
+ export { default as GitRef, } from './components/molecules/GitRef.svelte';
55
61
  export { default as IconButton } from './components/molecules/IconButton.svelte';
56
62
  export { default as KeyValue, } from './components/molecules/KeyValue.svelte';
57
63
  export { default as LoadMore } from './components/molecules/LoadMore.svelte';
@@ -74,6 +80,7 @@ export { default as Toaster } from './components/molecules/Toaster.svelte';
74
80
  export { default as Toggle } from './components/molecules/Toggle.svelte';
75
81
  export { default as Tooltip } from './components/molecules/Tooltip.svelte';
76
82
  export { default as Truncate } from './components/molecules/Truncate.svelte';
83
+ export { default as WorkingDir } from './components/molecules/WorkingDir.svelte';
77
84
  // ---- organisms ----
78
85
  export { default as DataTable, } from './components/organisms/DataTable.svelte';
79
86
  export { default as FilterSearchBar } from './components/organisms/FilterSearchBar.svelte';
@@ -87,3 +94,4 @@ export { toasts, } from './stores/toast.svelte';
87
94
  export { formatTimestamp, localTimeZone, relativeTime, } from './timestamp';
88
95
  export { canonicalTone } from './tone';
89
96
  export { truncate } from './truncate';
97
+ export { normalizeWorkingDir, workingDirCandidates } from './working-dir';
@@ -1,10 +1,10 @@
1
1
  export type TimeInput = Date | number | string;
2
2
  /**
3
3
  * Which slice of the instant the inline text shows. Orthogonal to the zone:
4
- * `date`/`time`/`datetime` honour the `utc` flag, while `iso` is always UTC
5
- * (by definition) and `relative` is zoneless.
4
+ * `date`/`time`/`datetime`/`short-iso` honour the `utc` flag, while `iso` is
5
+ * always UTC (by definition) and `relative` is zoneless.
6
6
  */
7
- export type TimestampMode = 'date' | 'time' | 'datetime' | 'relative' | 'iso';
7
+ export type TimestampMode = 'date' | 'time' | 'datetime' | 'relative' | 'iso' | 'short-iso';
8
8
  /**
9
9
  * Coerce a loose input to a Date, or null when it's missing or can't be parsed.
10
10
  * Accepting null/undefined lets callers pass an optional field straight through
@@ -20,6 +20,12 @@ export declare function toISO(d: Date): string;
20
20
  * without the off-by-one a local midnight-UTC value otherwise shows.
21
21
  */
22
22
  export declare function toLocale(d: Date, parts?: 'date' | 'time' | 'datetime', utc?: boolean): string;
23
+ /**
24
+ * Calendar date as `YYYY-MM-DD`, locale-independent — in UTC or, with
25
+ * `utc=false`, the viewer's zone (so a local evening past midnight UTC still
26
+ * reads as the viewer's day).
27
+ */
28
+ export declare function toShortISO(d: Date, utc?: boolean): string;
23
29
  /** Unix epoch in whole seconds. */
24
30
  export declare function toEpochSeconds(d: Date): number;
25
31
  /** The viewer's IANA time zone — `Asia/Tokyo`, `UTC`, … */
@@ -38,7 +44,7 @@ export declare function localTimeZone(): string;
38
44
  export declare function relativeTime(value: TimeInput | null | undefined, now?: number, precision?: boolean): string;
39
45
  /**
40
46
  * Render a date in the chosen inline mode. `utc` selects UTC over the viewer's
41
- * zone for the date/time/datetime modes (ignored by `iso`, always UTC, and
42
- * `relative`, zoneless). Returns '' for unparseable input.
47
+ * zone for the date/time/datetime/short-iso modes (ignored by `iso`, always
48
+ * UTC, and `relative`, zoneless). Returns '' for unparseable input.
43
49
  */
44
50
  export declare function formatTimestamp(value: TimeInput | null | undefined, mode: TimestampMode, now?: number, utc?: boolean, precision?: boolean): string;
package/dist/timestamp.js CHANGED
@@ -41,6 +41,18 @@ export function toLocale(d, parts = 'datetime', utc = false) {
41
41
  }
42
42
  return new Intl.DateTimeFormat(undefined, opts).format(d);
43
43
  }
44
+ /**
45
+ * Calendar date as `YYYY-MM-DD`, locale-independent — in UTC or, with
46
+ * `utc=false`, the viewer's zone (so a local evening past midnight UTC still
47
+ * reads as the viewer's day).
48
+ */
49
+ export function toShortISO(d, utc = true) {
50
+ const y = utc ? d.getUTCFullYear() : d.getFullYear();
51
+ const m = (utc ? d.getUTCMonth() : d.getMonth()) + 1;
52
+ const day = utc ? d.getUTCDate() : d.getDate();
53
+ const pad = (n, w = 2) => String(n).padStart(w, '0');
54
+ return `${pad(y, 4)}-${pad(m)}-${pad(day)}`;
55
+ }
44
56
  /** Unix epoch in whole seconds. */
45
57
  export function toEpochSeconds(d) {
46
58
  return Math.floor(d.getTime() / 1000);
@@ -103,8 +115,8 @@ export function relativeTime(value, now = Date.now(), precision = false) {
103
115
  }
104
116
  /**
105
117
  * Render a date in the chosen inline mode. `utc` selects UTC over the viewer's
106
- * zone for the date/time/datetime modes (ignored by `iso`, always UTC, and
107
- * `relative`, zoneless). Returns '' for unparseable input.
118
+ * zone for the date/time/datetime/short-iso modes (ignored by `iso`, always
119
+ * UTC, and `relative`, zoneless). Returns '' for unparseable input.
108
120
  */
109
121
  export function formatTimestamp(value, mode, now, utc = false, precision = false) {
110
122
  const d = toDate(value);
@@ -113,6 +125,8 @@ export function formatTimestamp(value, mode, now, utc = false, precision = false
113
125
  switch (mode) {
114
126
  case 'iso':
115
127
  return toISO(d);
128
+ case 'short-iso':
129
+ return toShortISO(d, utc);
116
130
  case 'date':
117
131
  case 'time':
118
132
  case 'datetime':
@@ -0,0 +1,12 @@
1
+ export interface WorkingDirOptions {
2
+ /** Visible chars the truncated leaf keeps before the ellipsis, at minimum. Default 18. */
3
+ minLeaf?: number;
4
+ }
5
+ /** Trailing slashes dropped; an empty or root-only path becomes `/`. */
6
+ export declare function normalizeWorkingDir(path: string): string;
7
+ /**
8
+ * Candidate renderings of `path`:
9
+ * full path → ancestors abbreviated to their first letter one at a time,
10
+ * left to right → leaf only → leaf end-truncated down to `minLeaf` chars.
11
+ */
12
+ export declare function workingDirCandidates(path: string, options?: WorkingDirOptions): string[];
@@ -0,0 +1,38 @@
1
+ // Fish-style path abbreviation candidates, richest → poorest. The WorkingDir
2
+ // molecule picks the first entry that fits its measured width; the last entry
3
+ // (the leaf clipped to `minLeaf` chars) is the hard floor.
4
+ import { truncate } from './truncate';
5
+ /** Trailing slashes dropped; an empty or root-only path becomes `/`. */
6
+ export function normalizeWorkingDir(path) {
7
+ return path.replace(/\/+$/, '') || '/';
8
+ }
9
+ /**
10
+ * Candidate renderings of `path`:
11
+ * full path → ancestors abbreviated to their first letter one at a time,
12
+ * left to right → leaf only → leaf end-truncated down to `minLeaf` chars.
13
+ */
14
+ export function workingDirCandidates(path, options = {}) {
15
+ const { minLeaf = 18 } = options;
16
+ const trimmed = path.replace(/\/+$/, '');
17
+ const absolute = trimmed.startsWith('/');
18
+ const segs = trimmed.split('/').filter(Boolean);
19
+ if (segs.length === 0)
20
+ return [trimmed || '/'];
21
+ const leaf = segs[segs.length - 1];
22
+ const parents = segs.slice(0, -1);
23
+ const out = [];
24
+ const push = (c) => {
25
+ if (out[out.length - 1] !== c)
26
+ out.push(c);
27
+ };
28
+ for (let n = 0; n <= parents.length; n++) {
29
+ const shown = parents.map((p, i) => (i < n ? [...p][0] : p));
30
+ const joined = [...shown, leaf].join('/');
31
+ push(absolute ? `/${joined}` : joined);
32
+ }
33
+ push(leaf);
34
+ for (let keep = [...leaf].length - 1; keep >= minLeaf; keep--) {
35
+ push(truncate(leaf, { max: keep + 1, mode: 'end' }));
36
+ }
37
+ return out;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorsk/tsumikit",
3
- "version": "0.35.1",
3
+ "version": "0.37.0",
4
4
  "description": "Minimal, dependency-free Svelte 5 + pure-CSS UI kit. Token-driven atoms, molecules & layouts with theming out of the box.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -57,20 +57,28 @@
57
57
  "format": "biome check --write .",
58
58
  "package": "svelte-kit sync && svelte-package && publint",
59
59
  "package:watch": "svelte-kit sync && svelte-package --watch",
60
- "prepublishOnly": "npm run package"
60
+ "prepublishOnly": "npm run package",
61
+ "design:bundle": "node .design-sync/build-bundle.mjs",
62
+ "design:verify": "node .design-sync/verify-bundle.mjs"
61
63
  },
62
64
  "peerDependencies": {
63
65
  "svelte": "^5.0.0"
64
66
  },
65
67
  "devDependencies": {
66
68
  "@biomejs/biome": "^2.2.0",
69
+ "@dorsk/kakehashi": "^0.1.1",
67
70
  "@sveltejs/adapter-static": "^3.0.8",
68
71
  "@sveltejs/kit": "^2.22.0",
69
72
  "@sveltejs/package": "^2.3.0",
70
73
  "@sveltejs/vite-plugin-svelte": "^6.0.0",
71
74
  "@types/node": "^25.9.3",
75
+ "esbuild": "^0.28.2",
76
+ "esbuild-svelte": "^0.9.5",
77
+ "jsdom": "^30.0.1",
72
78
  "lefthook": "^1.7.0",
73
79
  "publint": "^0.2.0",
80
+ "react": "^19.2.8",
81
+ "react-dom": "^19.2.8",
74
82
  "svelte": "^5.0.0",
75
83
  "svelte-check": "^4.0.0",
76
84
  "typescript": "^5.0.0",