@charcuterie/ui 3.0.0 → 3.2.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 (130) hide show
  1. package/README.md +10 -0
  2. package/dist/Badge/Badge.d.ts +33 -3
  3. package/dist/Badge/Badge.d.ts.map +1 -1
  4. package/dist/Badge/Badge.js +20 -2
  5. package/dist/Badge/Badge.js.map +1 -1
  6. package/dist/Board/Board.d.ts +119 -0
  7. package/dist/Board/Board.d.ts.map +1 -0
  8. package/dist/Board/Board.js +165 -0
  9. package/dist/Board/Board.js.map +1 -0
  10. package/dist/Board/BoardCard.d.ts +120 -0
  11. package/dist/Board/BoardCard.d.ts.map +1 -0
  12. package/dist/Board/BoardCard.js +77 -0
  13. package/dist/Board/BoardCard.js.map +1 -0
  14. package/dist/Board/BoardLaneList.d.ts +103 -0
  15. package/dist/Board/BoardLaneList.d.ts.map +1 -0
  16. package/dist/Board/BoardLaneList.js +69 -0
  17. package/dist/Board/BoardLaneList.js.map +1 -0
  18. package/dist/Board/boardMove.d.ts +116 -0
  19. package/dist/Board/boardMove.d.ts.map +1 -0
  20. package/dist/Board/boardMove.js +116 -0
  21. package/dist/Board/boardMove.js.map +1 -0
  22. package/dist/Board/useBoardDrag.d.ts +44 -0
  23. package/dist/Board/useBoardDrag.d.ts.map +1 -0
  24. package/dist/Board/useBoardDrag.js +237 -0
  25. package/dist/Board/useBoardDrag.js.map +1 -0
  26. package/dist/Checkbox/Checkbox.d.ts.map +1 -1
  27. package/dist/Checkbox/Checkbox.js +15 -4
  28. package/dist/Checkbox/Checkbox.js.map +1 -1
  29. package/dist/DataTable/DataTable.d.ts +159 -0
  30. package/dist/DataTable/DataTable.d.ts.map +1 -0
  31. package/dist/DataTable/DataTable.js +197 -0
  32. package/dist/DataTable/DataTable.js.map +1 -0
  33. package/dist/DatePicker/DateGrid.d.ts +79 -0
  34. package/dist/DatePicker/DateGrid.d.ts.map +1 -0
  35. package/dist/DatePicker/DateGrid.js +220 -0
  36. package/dist/DatePicker/DateGrid.js.map +1 -0
  37. package/dist/DatePicker/DatePicker.d.ts +138 -0
  38. package/dist/DatePicker/DatePicker.d.ts.map +1 -0
  39. package/dist/DatePicker/DatePicker.js +384 -0
  40. package/dist/DatePicker/DatePicker.js.map +1 -0
  41. package/dist/DatePicker/datePresets.d.ts +29 -0
  42. package/dist/DatePicker/datePresets.d.ts.map +1 -0
  43. package/dist/DatePicker/datePresets.js +28 -0
  44. package/dist/DatePicker/datePresets.js.map +1 -0
  45. package/dist/DatePicker/parseDateInput.d.ts +106 -0
  46. package/dist/DatePicker/parseDateInput.d.ts.map +1 -0
  47. package/dist/DatePicker/parseDateInput.js +419 -0
  48. package/dist/DatePicker/parseDateInput.js.map +1 -0
  49. package/dist/DatePicker/plainDate.d.ts +167 -0
  50. package/dist/DatePicker/plainDate.d.ts.map +1 -0
  51. package/dist/DatePicker/plainDate.js +272 -0
  52. package/dist/DatePicker/plainDate.js.map +1 -0
  53. package/dist/Dialog/Dialog.d.ts +12 -2
  54. package/dist/Dialog/Dialog.d.ts.map +1 -1
  55. package/dist/Dialog/Dialog.js +2 -2
  56. package/dist/Dialog/Dialog.js.map +1 -1
  57. package/dist/MarkdownEditor/MarkdownEditor.d.ts +147 -0
  58. package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  59. package/dist/MarkdownEditor/MarkdownEditor.js +492 -0
  60. package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -0
  61. package/dist/MarkdownEditor/markdownCommands.d.ts +202 -0
  62. package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -0
  63. package/dist/MarkdownEditor/markdownCommands.js +379 -0
  64. package/dist/MarkdownEditor/markdownCommands.js.map +1 -0
  65. package/dist/MarkdownEditor/markdownSpans.d.ts +92 -0
  66. package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -0
  67. package/dist/MarkdownEditor/markdownSpans.js +303 -0
  68. package/dist/MarkdownEditor/markdownSpans.js.map +1 -0
  69. package/dist/Modal/Modal.d.ts +6 -2
  70. package/dist/Modal/Modal.d.ts.map +1 -1
  71. package/dist/Modal/Modal.js +1 -1
  72. package/dist/Modal/Modal.js.map +1 -1
  73. package/dist/Overlay/OverlayPanel.d.ts +13 -2
  74. package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
  75. package/dist/Overlay/OverlayPanel.js +5 -1
  76. package/dist/Overlay/OverlayPanel.js.map +1 -1
  77. package/dist/categoricalStyles.d.ts +53 -0
  78. package/dist/categoricalStyles.d.ts.map +1 -0
  79. package/dist/categoricalStyles.js +195 -0
  80. package/dist/categoricalStyles.js.map +1 -0
  81. package/dist/index.d.ts +22 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +11 -0
  84. package/dist/index.js.map +1 -1
  85. package/package.json +2 -2
  86. package/src/Badge/Badge.mdx +46 -0
  87. package/src/Badge/Badge.stories.tsx +98 -4
  88. package/src/Badge/Badge.test.tsx +157 -2
  89. package/src/Badge/Badge.tsx +49 -3
  90. package/src/Board/Board.mdx +199 -0
  91. package/src/Board/Board.stories.tsx +707 -0
  92. package/src/Board/Board.test.tsx +310 -0
  93. package/src/Board/Board.tsx +333 -0
  94. package/src/Board/BoardCard.tsx +290 -0
  95. package/src/Board/BoardLaneList.tsx +275 -0
  96. package/src/Board/boardMove.test.ts +213 -0
  97. package/src/Board/boardMove.ts +225 -0
  98. package/src/Board/useBoardDrag.ts +413 -0
  99. package/src/Checkbox/Checkbox.tsx +34 -3
  100. package/src/DataTable/DataTable.mdx +123 -0
  101. package/src/DataTable/DataTable.stories.tsx +411 -0
  102. package/src/DataTable/DataTable.test.tsx +386 -0
  103. package/src/DataTable/DataTable.tsx +497 -0
  104. package/src/DatePicker/DateGrid.tsx +467 -0
  105. package/src/DatePicker/DatePicker.mdx +170 -0
  106. package/src/DatePicker/DatePicker.stories.tsx +268 -0
  107. package/src/DatePicker/DatePicker.test.tsx +455 -0
  108. package/src/DatePicker/DatePicker.tsx +852 -0
  109. package/src/DatePicker/datePresets.ts +34 -0
  110. package/src/DatePicker/parseDateInput.test.ts +187 -0
  111. package/src/DatePicker/parseDateInput.ts +629 -0
  112. package/src/DatePicker/plainDate.test.ts +375 -0
  113. package/src/DatePicker/plainDate.ts +465 -0
  114. package/src/Dialog/Dialog.stories.tsx +48 -0
  115. package/src/Dialog/Dialog.test.tsx +30 -0
  116. package/src/Dialog/Dialog.tsx +13 -1
  117. package/src/MarkdownEditor/MarkdownEditor.mdx +189 -0
  118. package/src/MarkdownEditor/MarkdownEditor.stories.tsx +267 -0
  119. package/src/MarkdownEditor/MarkdownEditor.test.tsx +627 -0
  120. package/src/MarkdownEditor/MarkdownEditor.tsx +862 -0
  121. package/src/MarkdownEditor/markdownCommands.test.ts +384 -0
  122. package/src/MarkdownEditor/markdownCommands.ts +566 -0
  123. package/src/MarkdownEditor/markdownSpans.test.ts +217 -0
  124. package/src/MarkdownEditor/markdownSpans.ts +458 -0
  125. package/src/Modal/Modal.tsx +7 -1
  126. package/src/Overlay/OverlayPanel.tsx +17 -1
  127. package/src/argTypes.storyHelpers.ts +39 -0
  128. package/src/categoricalStyles.ts +244 -0
  129. package/src/index.ts +89 -0
  130. package/src/sourceRules.test.ts +52 -1
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The shortcut row, in its own module.
3
+ *
4
+ * Its own file for two reasons, one design and one mechanical. The
5
+ * design one: a preset is an **offset from today**, not a date, so
6
+ * the preset row cannot become the one thing in the component that
7
+ * reads the system clock behind `today`'s back. The mechanical one:
8
+ * the barrel's assist merges same-source exports into one block, and
9
+ * `sourceRules.test.ts` asserts a literal `export { <Name> }` line
10
+ * for every component — so a component file with a second named
11
+ * export cannot be barrelled the way that rule expects. Same
12
+ * arrangement as `Toolbar/chooseVisibleCount.ts`.
13
+ */
14
+
15
+ export type DatePreset = {
16
+ /** Whole days from `today`. Negative is allowed. */
17
+ days: number
18
+ label: string
19
+ }
20
+
21
+ /**
22
+ * Words, not glyphs — the house rule, and it is the right default
23
+ * here anyway: "Today" is unambiguous in a way an icon of a calendar
24
+ * with a dot on it is not.
25
+ *
26
+ * Three, because a shortcut row that needs scanning is not a
27
+ * shortcut. `presets={[]}` removes it; a consumer with its own
28
+ * cadence (Docket's 14-day staleness) passes its own.
29
+ */
30
+ export const DEFAULT_DATE_PRESETS: readonly DatePreset[] = [
31
+ { days: 0, label: "Today" },
32
+ { days: 1, label: "Tomorrow" },
33
+ { days: 7, label: "Next week" },
34
+ ]
@@ -0,0 +1,187 @@
1
+ /**
2
+ * The typed-input grammar.
3
+ *
4
+ * Every case resolves against a **fixed** `today` — Wednesday
5
+ * 19 August 2026 — because a relative-date parser tested against the
6
+ * real clock is a suite that passes on the day it is written, goes
7
+ * red the following Friday, and gets `.skip`ped.
8
+ *
9
+ * The interesting half of this file is the failures. A parser that
10
+ * only proves it accepts `8/19` is a parser nobody has checked for
11
+ * the thing that actually hurts: quietly accepting something as the
12
+ * wrong date.
13
+ */
14
+
15
+ import { expect, test } from "vitest"
16
+
17
+ import { parseDateInput } from "./parseDateInput.ts"
18
+ import { toIsoDate } from "./plainDate.ts"
19
+
20
+ const TODAY = { day: 19, month: 8, year: 2026 }
21
+
22
+ const parse = (text: string, locale = "en-US") =>
23
+ parseDateInput(text, { locale, today: TODAY })
24
+
25
+ const parsedIso = (text: string, locale?: string) => {
26
+ const result = parse(text, locale)
27
+
28
+ return result.kind === "date"
29
+ ? toIsoDate(result.date)
30
+ : result
31
+ }
32
+
33
+ test("ISO is accepted first, and is never read as a d-m-y", () => {
34
+ expect(parsedIso("2026-08-19")).toBe("2026-08-19")
35
+ expect(parsedIso("2026-01-05")).toBe("2026-01-05")
36
+ })
37
+
38
+ test("the relative words resolve against the injected today", () => {
39
+ expect(parsedIso("today")).toBe("2026-08-19")
40
+ expect(parsedIso("Tomorrow")).toBe("2026-08-20")
41
+ expect(parsedIso("yesterday")).toBe("2026-08-18")
42
+ expect(parsedIso("tmrw")).toBe("2026-08-20")
43
+ })
44
+
45
+ test("signed offsets are the form a staleness threshold is typed in", () => {
46
+ expect(parsedIso("+14d")).toBe("2026-09-02")
47
+ expect(parsedIso("+14")).toBe("2026-09-02")
48
+ expect(parsedIso("-7d")).toBe("2026-08-12")
49
+ expect(parsedIso("+2w")).toBe("2026-09-02")
50
+ expect(parsedIso("+1m")).toBe("2026-09-19")
51
+ expect(parsedIso("+1y")).toBe("2027-08-19")
52
+ expect(parsedIso("in 3 days")).toBe("2026-08-22")
53
+ expect(parsedIso("in 2 weeks")).toBe("2026-09-02")
54
+ })
55
+
56
+ test("next week / next month step the unit, not seven days of month", () => {
57
+ expect(parsedIso("next week")).toBe("2026-08-26")
58
+ expect(parsedIso("next month")).toBe("2026-09-19")
59
+ expect(parsedIso("last week")).toBe("2026-08-12")
60
+ expect(parsedIso("next year")).toBe("2027-08-19")
61
+ })
62
+
63
+ test("a weekday means the next one, and never today", () => {
64
+ // Today is a Wednesday.
65
+ expect(parsedIso("fri")).toBe("2026-08-21")
66
+ expect(parsedIso("next friday")).toBe("2026-08-21")
67
+ expect(parsedIso("last fri")).toBe("2026-08-14")
68
+
69
+ // The case that makes "or today if today is it" wrong: `next wed`
70
+ // on a Wednesday has to move, or the phrase is a no-op on the one
71
+ // day somebody would type it.
72
+ expect(parsedIso("next wed")).toBe("2026-08-26")
73
+ expect(parsedIso("mon")).toBe("2026-08-24")
74
+ })
75
+
76
+ test("month names parse in either order, with or without a year", () => {
77
+ expect(parsedIso("aug 19")).toBe("2026-08-19")
78
+ expect(parsedIso("19 aug")).toBe("2026-08-19")
79
+ expect(parsedIso("August 19, 2027")).toBe("2027-08-19")
80
+ expect(parsedIso("19 august 2027")).toBe("2027-08-19")
81
+ expect(parsedIso("sep 1")).toBe("2026-09-01")
82
+ })
83
+
84
+ test("numeric input follows the locale's own field order", () => {
85
+ expect(parsedIso("8/19")).toBe("2026-08-19")
86
+ expect(parsedIso("8/19/2026")).toBe("2026-08-19")
87
+
88
+ // The genuinely ambiguous one. Both readings are real dates, so the
89
+ // locale decides and the component echoes what it decided.
90
+ expect(parsedIso("3/4", "en-US")).toBe("2026-03-04")
91
+ expect(parsedIso("3/4", "en-GB")).toBe("2026-04-03")
92
+ expect(parsedIso("19/8", "en-GB")).toBe("2026-08-19")
93
+ })
94
+
95
+ test("a reading is swapped only when it is the only valid one", () => {
96
+ // There is no nineteenth month, so `19/8` in a month-first locale
97
+ // has exactly one reading and taking it is deduction, not taste.
98
+ expect(parsedIso("19/8", "en-US")).toBe("2026-08-19")
99
+
100
+ // …and when both readings work, nothing is swapped.
101
+ expect(parsedIso("4/3", "en-US")).toBe("2026-04-03")
102
+ })
103
+
104
+ test("a two-digit year uses the POSIX window, not the current century", () => {
105
+ expect(parsedIso("8/19/26")).toBe("2026-08-19")
106
+ expect(parsedIso("8/19/68")).toBe("2068-08-19")
107
+ expect(parsedIso("8/19/69")).toBe("1969-08-19")
108
+ expect(parsedIso("8/19/99")).toBe("1999-08-19")
109
+ })
110
+
111
+ test("a bare number is the day of the month on screen", () => {
112
+ expect(parsedIso("19")).toBe("2026-08-19")
113
+ expect(parsedIso("1")).toBe("2026-08-01")
114
+ expect(parsedIso("31")).toBe("2026-08-31")
115
+ })
116
+
117
+ test("an ambiguous month or weekday prefix is a named failure, not a pick", () => {
118
+ // The whole point. `ju` is June and July; a parser that takes the
119
+ // first match files a July task in June and nothing ever says so.
120
+ const june = parse("ju 19")
121
+
122
+ expect(june.kind).toBe("unparsed")
123
+
124
+ expect(
125
+ june.kind === "unparsed" ? june.reason : "",
126
+ ).toContain("June or July")
127
+
128
+ const saturday = parse("s")
129
+
130
+ expect(saturday.kind).toBe("unparsed")
131
+
132
+ expect(
133
+ saturday.kind === "unparsed" ? saturday.reason : "",
134
+ ).toContain("Sunday or Saturday")
135
+
136
+ // Type one more letter and it resolves.
137
+ expect(parsedIso("jul 19")).toBe("2026-07-19")
138
+ expect(parsedIso("jun 19")).toBe("2026-06-19")
139
+ })
140
+
141
+ test("an impossible date is refused, with the reason", () => {
142
+ const result = parse("2/30")
143
+
144
+ expect(result.kind).toBe("unparsed")
145
+
146
+ expect(
147
+ result.kind === "unparsed" ? result.reason : "",
148
+ ).toContain("no 30/2")
149
+
150
+ expect(parse("2026-02-30").kind).toBe("unparsed")
151
+ expect(parse("feb 31").kind).toBe("unparsed")
152
+ })
153
+
154
+ test("a partial or nonsense input never becomes a nearest guess", () => {
155
+ // `8/` is not the first of August, `next` is not next anything, and
156
+ // `2026` is not a day.
157
+ for (const text of [
158
+ "8/",
159
+ "/19",
160
+ "next",
161
+ "2026",
162
+ "soon",
163
+ "the 19th",
164
+ "19th aug",
165
+ "aug",
166
+ "--",
167
+ ]) {
168
+ expect(parse(text).kind, text).toBe("unparsed")
169
+ }
170
+ })
171
+
172
+ test("empty is its own outcome, because clearing a date is legitimate", () => {
173
+ expect(parse("").kind).toBe("empty")
174
+ expect(parse(" ").kind).toBe("empty")
175
+ })
176
+
177
+ test("accents and casing do not have to be typed", () => {
178
+ expect(parsedIso("19 fevrier 2027", "fr-FR")).toBe(
179
+ "2027-02-19",
180
+ )
181
+
182
+ expect(parsedIso("19 février 2027", "fr-FR")).toBe(
183
+ "2027-02-19",
184
+ )
185
+
186
+ expect(parsedIso("AUG 19")).toBe("2026-08-19")
187
+ })