@stcn52/pro 0.0.0-stage → 0.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 (163) hide show
  1. package/CHANGELOG.md +615 -0
  2. package/CONVENTIONS.md +152 -0
  3. package/LICENSE +21 -0
  4. package/README.md +226 -2
  5. package/RELEASING.md +51 -0
  6. package/THIRD_PARTY_NOTICES.md +52 -0
  7. package/dist/index.cjs +23153 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.d.cts +5067 -0
  10. package/dist/index.d.ts +5067 -0
  11. package/dist/index.js +22941 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/styles.css +10475 -0
  14. package/dist/tokens.css +322 -0
  15. package/docs/antd-alignment-plan.md +983 -0
  16. package/docs/api.md +3654 -0
  17. package/docs/components.md +1702 -0
  18. package/docs/measurements.md +152 -0
  19. package/docs/qa/README.md +50 -0
  20. package/docs/qa/browser-checks.json +394 -0
  21. package/docs/qa/d-chrome-checklist-dark.png +0 -0
  22. package/docs/qa/d-chrome-checks.json +234 -0
  23. package/docs/qa/d-chrome-detail-dark.png +0 -0
  24. package/docs/qa/d-chrome-filters-dark.png +0 -0
  25. package/docs/qa/d-chrome-shell-dark.png +0 -0
  26. package/docs/qa/d-detail-checks.json +222 -0
  27. package/docs/qa/d-detail-comments-failed-dark.png +0 -0
  28. package/docs/qa/d-detail-preview-dark.png +0 -0
  29. package/docs/qa/d-entity-checks.json +294 -0
  30. package/docs/qa/d-entity-failed-dark.png +0 -0
  31. package/docs/qa/d-workbench-canvas-dark.png +0 -0
  32. package/docs/qa/d-workbench-checks.json +338 -0
  33. package/docs/qa/d-workbench-edit-failed-dark.png +0 -0
  34. package/docs/qa/d-workbench-roadmap-dark.png +0 -0
  35. package/docs/qa/d-workbench-wizard-failed-dark.png +0 -0
  36. package/docs/qa/date-range-mobile-dark.jpg +0 -0
  37. package/docs/qa/p0-cascader-checks.json +228 -0
  38. package/docs/qa/p0-cascader-multiple-dark.png +0 -0
  39. package/docs/qa/p0-config-checks.json +430 -0
  40. package/docs/qa/p0-config-nested-dark.png +0 -0
  41. package/docs/qa/p0-date-checks.json +595 -0
  42. package/docs/qa/p0-date-time-dark.png +0 -0
  43. package/docs/qa/p0-form-lifecycle-checks.json +30 -0
  44. package/docs/qa/p0-form-lifecycle.png +0 -0
  45. package/docs/qa/p0-select-checks.json +378 -0
  46. package/docs/qa/p0-select-virtual-dark.png +0 -0
  47. package/docs/qa/p0-table-checks.json +290 -0
  48. package/docs/qa/p0-table-virtual-dark.png +0 -0
  49. package/docs/qa/p0-transfer-checks.json +322 -0
  50. package/docs/qa/p0-transfer-pagination-dark.png +0 -0
  51. package/docs/qa/p0-tree-checks.json +242 -0
  52. package/docs/qa/p0-tree-range-dark.png +0 -0
  53. package/docs/qa/p1-app-browser-checks.json +34 -0
  54. package/docs/qa/p1-app-feedback-dark.png +0 -0
  55. package/docs/qa/p1-avatar-checks.json +370 -0
  56. package/docs/qa/p1-avatar-dark.png +0 -0
  57. package/docs/qa/p1-browser-checks.json +218 -0
  58. package/docs/qa/p1-card-checks.json +262 -0
  59. package/docs/qa/p1-card-dark.png +0 -0
  60. package/docs/qa/p1-content-navigation-browser-checks.json +114 -0
  61. package/docs/qa/p1-controls-browser-checks.json +86 -0
  62. package/docs/qa/p1-controls-desktop-dark.png +0 -0
  63. package/docs/qa/p1-dialog-nested-dark.png +0 -0
  64. package/docs/qa/p1-display-browser-checks.json +114 -0
  65. package/docs/qa/p1-display-desktop-dark.png +0 -0
  66. package/docs/qa/p1-divider-dark.png +0 -0
  67. package/docs/qa/p1-drawer-browser-checks.json +302 -0
  68. package/docs/qa/p1-drawer-rtl-dark.png +0 -0
  69. package/docs/qa/p1-general-input-browser-checks.json +114 -0
  70. package/docs/qa/p1-general-input-desktop-dark.png +0 -0
  71. package/docs/qa/p1-image-browser-checks.json +38 -0
  72. package/docs/qa/p1-image-preview-dark.png +0 -0
  73. package/docs/qa/p1-inline-browser-checks.json +58 -0
  74. package/docs/qa/p1-inline-desktop-dark.png +0 -0
  75. package/docs/qa/p1-layout-browser-checks.json +114 -0
  76. package/docs/qa/p1-layout-desktop-dark.png +0 -0
  77. package/docs/qa/p1-menu-checks.json +357 -0
  78. package/docs/qa/p1-menu-long-dark.png +0 -0
  79. package/docs/qa/p1-nav-dark.png +0 -0
  80. package/docs/qa/p1-nav-sidebar-checks.json +218 -0
  81. package/docs/qa/p1-navigation-browser-checks.json +114 -0
  82. package/docs/qa/p1-navigation-mobile-dark.png +0 -0
  83. package/docs/qa/p1-pagination-checks.json +309 -0
  84. package/docs/qa/p1-pagination-dark.png +0 -0
  85. package/docs/qa/p1-pagination-mobile-dark.png +0 -0
  86. package/docs/qa/p1-popup-actions-browser-checks.json +58 -0
  87. package/docs/qa/p1-popup-actions-desktop-dark.png +0 -0
  88. package/docs/qa/p1-progress-browser-checks.json +30 -0
  89. package/docs/qa/p1-progress-desktop-dark.png +0 -0
  90. package/docs/qa/p1-rate-half-desktop-dark.png +0 -0
  91. package/docs/qa/p1-segment-checks.json +426 -0
  92. package/docs/qa/p1-segment-dark.png +0 -0
  93. package/docs/qa/p1-sidebar-dark.png +0 -0
  94. package/docs/qa/p1-slider-rate-browser-checks.json +114 -0
  95. package/docs/qa/p1-states-browser-checks.json +34 -0
  96. package/docs/qa/p1-states-checks.json +342 -0
  97. package/docs/qa/p1-states-dark.png +0 -0
  98. package/docs/qa/p1-states-mobile-dark.png +0 -0
  99. package/docs/qa/p1-tabs-editable-dark.png +0 -0
  100. package/docs/qa/p1-tag-dark.png +0 -0
  101. package/docs/qa/p1-tag-divider-checks.json +330 -0
  102. package/docs/qa/p1-upload-browser-checks.json +30 -0
  103. package/docs/qa/p1-upload-list-dark.png +0 -0
  104. package/docs/qa/p2-ai-panel-checks.json +401 -0
  105. package/docs/qa/p2-ai-panel-dark.png +0 -0
  106. package/docs/qa/p2-alert-dark.png +0 -0
  107. package/docs/qa/p2-app-final-checks.json +309 -0
  108. package/docs/qa/p2-app-final-dark.png +0 -0
  109. package/docs/qa/p2-badge-alert-checks.json +466 -0
  110. package/docs/qa/p2-beam-motion-checks.json +58 -0
  111. package/docs/qa/p2-calendar-dark.png +0 -0
  112. package/docs/qa/p2-calendar-timeline-checks.json +254 -0
  113. package/docs/qa/p2-charts-checks.json +242 -0
  114. package/docs/qa/p2-charts-dark.png +0 -0
  115. package/docs/qa/p2-color-gradient-dark.png +0 -0
  116. package/docs/qa/p2-content-navigation-checks.json +794 -0
  117. package/docs/qa/p2-dialog-popover-dark.png +0 -0
  118. package/docs/qa/p2-display-checks.json +128 -0
  119. package/docs/qa/p2-display-dark.png +0 -0
  120. package/docs/qa/p2-drawer-final-dark.png +0 -0
  121. package/docs/qa/p2-extras-checks.json +482 -0
  122. package/docs/qa/p2-general-inputs-checks.json +154 -0
  123. package/docs/qa/p2-general-inputs-dark.png +0 -0
  124. package/docs/qa/p2-icon-checks.json +466 -0
  125. package/docs/qa/p2-icon-dark.png +0 -0
  126. package/docs/qa/p2-image-dark.png +0 -0
  127. package/docs/qa/p2-inline-editors-checks.json +199 -0
  128. package/docs/qa/p2-input-button-checks.json +778 -0
  129. package/docs/qa/p2-input-dark.png +0 -0
  130. package/docs/qa/p2-layout-final-checks.json +136 -0
  131. package/docs/qa/p2-layout-final-dark.png +0 -0
  132. package/docs/qa/p2-lists-checks.json +290 -0
  133. package/docs/qa/p2-masonry-dark.png +0 -0
  134. package/docs/qa/p2-media-checks.json +212 -0
  135. package/docs/qa/p2-mentions-color-checks.json +362 -0
  136. package/docs/qa/p2-overlay-checks.json +370 -0
  137. package/docs/qa/p2-people-picker-dark.png +0 -0
  138. package/docs/qa/p2-popconfirm-final-dark.png +0 -0
  139. package/docs/qa/p2-popup-final-checks.json +223 -0
  140. package/docs/qa/p2-qr-browser-decode.json +30 -0
  141. package/docs/qa/p2-quick-select-dark.png +0 -0
  142. package/docs/qa/p2-quick-text-dark.png +0 -0
  143. package/docs/qa/p2-rate-dark.png +0 -0
  144. package/docs/qa/p2-scroll-navigation-checks.json +198 -0
  145. package/docs/qa/p2-scroll-navigation-dark.png +0 -0
  146. package/docs/qa/p2-selection-bar-checks.json +302 -0
  147. package/docs/qa/p2-selection-bar-dark.png +0 -0
  148. package/docs/qa/p2-slider-rate-checks.json +262 -0
  149. package/docs/qa/p2-switch-dark.png +0 -0
  150. package/docs/qa/p2-tabs-dark.png +0 -0
  151. package/docs/qa/p2-timeline-dark.png +0 -0
  152. package/docs/qa/p2-toast-dark.png +0 -0
  153. package/docs/qa/p2-toggle-checks.json +834 -0
  154. package/docs/qa/p2-tour-dark.png +0 -0
  155. package/docs/qa/p2-upload-dark.png +0 -0
  156. package/docs/qa/table-details.md +26 -0
  157. package/docs/qa/table-mobile-dark.jpg +0 -0
  158. package/docs/qa/transfer-mobile-light.jpg +0 -0
  159. package/docs/qa/tree-browser-checks.json +226 -0
  160. package/docs/qa/tree-details.md +25 -0
  161. package/docs/qa/tree-directory-mobile-dark.jpg +0 -0
  162. package/docs/tokens.md +255 -0
  163. package/package.json +92 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,615 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@stcn52/pro` are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
6
+ the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ - Clear all 13 lint warnings: publish controlled props before layout effects, reset closed overlays without effect cascades, isolate ref-backed event handlers and render composer tools as components; enforce hook checks and a zero-warning verification gate.
11
+
12
+ - Ship editors: validate owned drag sessions, quarter/year boundaries and wizard drafts; wait for real workbench imports/deletes/edits and preserve new selection, parse quoted multiline CSV safely, guard queued callbacks after unmount, and contain mobile canvas cards.
13
+
14
+ - Ship entities: await real entity/picker/share submissions, retain failed drafts and isolate reopened sessions; deduplicate relation counts without dropping off-page IDs, respect provider disabled, validate scheduled recipients, and copy only host-supplied links after confirmed success.
15
+
16
+ - Ship detail: asynchronous comment submission with draft-preserving retry, cyclic thread safety, provider-aware relationship controls, attachment reader/timer cleanup and latest callbacks, explicit preview download stand-ins and CSV formula protection.
17
+
18
+ - Ship chrome: provider-aware rail/header/tools, per-rail disabled overrides, safe empty filters and operator resets, localized business controls, F2/IME title editing, finite badges, controlled inline editing focus and responsive reading surfaces.
19
+
20
+ - App feedback: inherit nested placement/caps, isolate closed message handles from reused keys, and settle all close subscribers while preserving reentrant notices and timers when host callbacks fail.
21
+
22
+ - Popup actions: drop blocked uncontrolled menus/confirmations, preserve controlled ownership and protect modified/IME open keys; localize confirmation labels/errors, retain zero content and normalize nonfinite drawer dimensions.
23
+
24
+ - Layout: localized sider/splitter controls and explicit sider disabled overrides; finite numeric dimensions/gaps/flex, responsive collapse deduplication, pointer capture completion and stale-drag/IME protection.
25
+
26
+ - Display: locale and explicit-null breadcrumb separators, fractional-only statistics; Typography protects IME commits and external focus, cancels stale async copy attempts before clipboard writes and localizes controls.
27
+
28
+ - Upload/Image: localize controls, preserve falsy rejection errors and latest async transfer configuration, avoid duplicate stale removals; drop blocked uncontrolled previews, normalize rotations and retain zero placeholders.
29
+
30
+ - General inputs: finite/IME-safe numeric stepping, duplicate suggestion/tree/time change suppression, inherited-disabled tree search overrides; localize numeric/tree controls and clock validity, discard blocked uncontrolled popups.
31
+
32
+ - Overlays: Escape dismisses one leaf layer, modal Tab includes related portals, nested popovers rise above their anchors; tooltips merge descriptions and fit/re-measure viewport edges, toasts pause for keyboard focus and normalize invalid durations.
33
+
34
+ - Badge/Alert: numeric-string caps and zero rules, finite overflow/offset handling, localized status/close labels and reentrant-safe afterClose tracking.
35
+
36
+ - Tabs/Collapse/Steps: recover owned focus after dynamic removal, hiding or disabling; preserve external focus during tab removal, localize editable labels and protect modified/IME navigation keys.
37
+
38
+ - Input/Buttons: IME-safe Enter and clear behavior, localized clear/password controls, existing-id Field labels and merged accessible feedback; zero-content actions and split-menu disabled overrides.
39
+
40
+ - Radio/Checkbox/Switch: native group container refs/attributes, zero-valued checkbox labels, duplicate radio selection suppression, wrapped radio groups and IME-safe switch keys.
41
+
42
+ - Slider/Rate: disabled and canceled completion guards, finite extreme ranges and valid marks; selected-star clearing, zero-count ratings, locale labels and hover resets.
43
+
44
+ - AiPanel: Promise submission locks, failed-draft retry, stale-session protection, locale/disabled and IME handling; share Dialog modal stacking and follow streamed text in the actual body scroll container.
45
+
46
+ - Inline editors: disabled/readOnly and field configuration forwarding, accessible synchronous validation, IME protection, safe clear/unassigned identifiers and dynamic option focus; PeoplePicker accepts host loading/error/retry.
47
+
48
+ - SelectionBar: respect disabled commands and global overrides; lock pending operations, retain failed selections and await all round-robin writes before reporting success.
49
+
50
+ - Charts: localized empty data, finite/extreme numeric geometry, proportion-safe donut totals, data descriptions and responsive legends; protect interactive scatter points.
51
+ - Icon: safe prototype-like-name fallback, accessible unknown glyphs, native span refs/attributes and bounded numeric sizes.
52
+ - States/Progress: visible default Skeleton geometry, bounded placeholder/step counts, locale and native refs; honor null progress formatting and wrap narrow feedback content.
53
+ - Nav/Sidebar: isolate overflow keyboard/disabled state, preserve host routes and native refs, track label sizing; localize sidebar controls and end resizing on lost pointer capture.
54
+ - Segment: single keyboard entry, dynamic focus recovery, duplicate selection suppression, native refs/custom content/block layout; Chip consumes provider disabled.
55
+ - Tag/Divider: native attributes/ref, custom tag icons and close-event isolation; locale/disabled overrides, dotted rules and wrapping RTL captions.
56
+ - Card: native section attributes/ref, compact/inner variants, Grid/Meta composition, localized loading and narrow-content wrapping.
57
+ - Avatar: numeric sizing, square shape, measured children scaling, Unicode initials, srcSet fallback, native refs and accessible stack overflow.
58
+ - Pagination: suppress current/empty paging notifications, bound numeric precision, discard disabled size-menu state and protect IME quick entry; verify controlled/default state and total changes.
59
+
60
+ - Menu/ContextMenu: single Tab entry, dynamic focus recovery, disabled branches and RTL nested Escape/backward handling; bounded long menus preserve internal scroll, and submenus flip into available viewport space.
61
+
62
+ - ConfigProvider: nested light/dark themes and merged CSS tokens now reach body portals; undefined token overrides inherit. Pagination and selector/date labels consume locale, table controls consume disabled, and RTL spacing, popup alignment and fixed-column offsets mirror correctly.
63
+
64
+ - DatePicker/DateRangePicker: local time confirmation, week/month/quarter/year modes, multiple dates, lazy presets, strict format parsing, controlled popups and shared date/time bounds. ISO string values and native refs remain unchanged.
65
+
66
+ - DataTable: hierarchical rows, nested headers, additive sort arrays, radio selection, fixed-height virtual windows and aggregate change events. Summary now receives processed roots before pagination; merged/detail/group bodies retain full rendering.
67
+
68
+ - Complete Cascader multiple/intermediate paths, shared Tree check conduction, field mapping,
69
+ controlled popups/search, rich labels and source-safe lazy loading with retry.
70
+
71
+ - Complete Tree/DirectoryTree cached range selection, expansion-independent directory picks,
72
+ leaf icons, RTL/IME behavior and native drag geometry. `onDrop.dropPosition` now uses
73
+ the target sibling index; `relativeDropPosition` exposes the previous -1/0/1 meaning.
74
+
75
+ - Complete Transfer independent controlled checks, directional move payloads, page-safe selections,
76
+ rich/custom lists, search hooks and native refs with guarded custom callbacks.
77
+
78
+ - Complete Select/MultiSelect grouped virtual choices, labeled-value caching, controlled opening,
79
+ clear controls, custom option/label/tag rendering and async states while preserving string callbacks.
80
+
81
+ - Add Carousel, target-aware modal Tour, real SVG/canvas QRCode, native Watermark and responsive SVG BorderBeam; reuse Dialog focus/stack behavior for Tour.
82
+
83
+ - Add Mentions with caret-safe insertion, IME and keyboard suggestions; add ColorPicker with solid/gradient HEX/RGB/HSB editing, alpha, presets and controlled opening.
84
+
85
+ - Add Form conditional/render items, selective updates, preserve policies and filtered focus/scroll options
86
+ while protecting StrictMode and dynamic list remounts.
87
+
88
+ - Add App-bound message/notification APIs and static host restoration; add keyed Toast updates,
89
+ destroy-all, close callbacks, timer cleanup and persistent-hover handling.
90
+
91
+ - Add real-file Upload with async preflight/manual mode, multipart XHR or cancellable custom requests,
92
+ progress/error lists, accept/count limits and drag/drop.
93
+
94
+ - Add native Image loading/fallback and controlled previews with zoom, rotation and explicit groups.
95
+
96
+ - Add four-edge Drawer sharing Dialog modal behavior, bounded dimensions and independent
97
+ keyboard, mask and close-button controls.
98
+
99
+ - Add Dropdown and Popconfirm with native button refs, existing Menu/Popover behavior,
100
+ controlled visibility and async confirmation retry/cancellation.
101
+
102
+ - Fix nested Dialog scroll locks, top-layer keyboard handling, focus restoration and hidden/disabled focus filtering.
103
+
104
+ - Add compound Layout, responsive Row/Col/Grid, Flex/Space/Compact and accessible Splitter
105
+ with controlled sizing, bounds, keyboard/pointer adjustment and collapse restoration.
106
+
107
+ - Add Breadcrumb, responsive Descriptions, string-preserving Statistic and compound Typography
108
+ with async copying, editing, expansion and native link/heading semantics.
109
+
110
+ - Add InputNumber, AutoComplete, TreeSelect and TimePicker with Form/config integration,
111
+ numeric drafts, IME-safe suggestions, reused Tree loading/checks and native clock validation.
112
+
113
+ - Extend Badge status/rich counts/RTL offsets and Alert banner/title/variants/custom close lifecycle.
114
+
115
+ - Add Input affixes, clear/count/status/variants with native reset and Form integration;
116
+ extend button shapes/ghost/danger, loading actions, RTL switch text/keyboard and group option attributes.
117
+ - Expand Tabs editing/lifecycle/placement, Collapse keyboard/extra actions and Steps item states.
118
+
119
+ - P1 navigation: controlled Menu selection/expansion and inline/horizontal modes,
120
+ independent-menu state isolation, RTL/disabled Nav and ContextMenu, controlled
121
+ Sidebar sizing and collapsed focus isolation. Share rich-label search text.
122
+
123
+ - P1: expand Pagination, Segment, Avatar, Tag, Card and Divider contracts;
124
+ preserve controlled DataTable pagination and add display/interaction regressions.
125
+
126
+ - Add absolute FormItem dependency paths with user-triggered transitive
127
+ revalidation, cyclic dependency protection and stale async-result regression coverage.
128
+
129
+ - Add opt-in fixed-height Select/MultiSelect virtual scrolling, complete-list
130
+ keyboard navigation, tags/token separators and distinct-value maxCount.
131
+ - Preserve virtual option focus during scrolling and prevent delayed Popover
132
+ autofocus from overriding user navigation; defer tokenization during IME input.
133
+
134
+ - Add nested Form name paths, subtree validation/reset, copied values and
135
+ FormList dynamic/nested arrays with stable keys; expose Form.Item/Form.List
136
+ aliases and guard unsafe paths, cycles and excessive depth/indexes.
137
+
138
+ - Add ConfigProvider locale/direction/disabled defaults and a flat-field Form
139
+ foundation with async validation, resets, watched values and submission.
140
+ - Existing core controls consume disabled defaults; portals retain language
141
+ and direction, and Select/SplitButton close interactive layers when disabled.
142
+
143
+ - Complete Tree hierarchy capabilities: controlled state, cascade/strict checks, multi-selection, two-level lazy loading and retry, search, connector lines/custom rendering, virtual scrolling, ref scrolling and drag lifecycle/drop rules.
144
+ - Add DirectoryTree with folder/file icons, click/double-click expansion and Ctrl/Meta/Shift selection; retain legacy Tree route and reorder APIs.
145
+
146
+ - Complete DataTable details: local/remote pagination, local sorting and column filters, disabled row selection, expandable details, hidden/wrapping/merged cells, summary/title/footer and scroll configuration.
147
+ - Fix grouped and merged-cell cursor navigation, auxiliary column alignment, embedded control clicks, loading/error feedback and fixed expansion-column geometry.
148
+
149
+ ### Added
150
+
151
+ - Select/MultiSelect shared search: rich-label text, custom filtering/sorting,
152
+ controlled queries, remote search callbacks, and enabled-option keyboard navigation.
153
+
154
+ - `Cascader`, `Transfer`, `DatePicker`, and `DateRangePicker`: searchable hierarchy,
155
+ dual-list selection, themed calendar and mutually constrained date ranges.
156
+
157
+ - `CheckboxGroup`, `PasswordInput`, and `Rate`, reusing the existing controls
158
+ with controlled/uncontrolled state, native keyboard interaction and no new dependencies.
159
+
160
+ - `Slider`, `Steps`, and `Alert`: native range input, accessible controlled step
161
+ navigation, and dismissible inline feedback. Includes stories, tests and docs.
162
+
163
+ - `Radio` / `RadioGroup`, `Tabs`, `Collapse`, and `Badge`, informed by Ant Design
164
+ component contracts and implemented with existing tokens and no new dependencies.
165
+ Includes native radio navigation, accessible tab panels, controlled/uncontrolled
166
+ selections, accordion mode, badge overflow, Storybook examples and tests.
167
+
168
+ ### Fixed
169
+
170
+ - MultiSelect disabled choices, nested labels, dialog/checkbox semantics, large
171
+ and invalid states, and clearing that preserves locked and unknown selections.
172
+ - Select popup declaration now matches its dialog container.
173
+
174
+ ### Changed
175
+
176
+ - Local release script now validates only with `--dry-run`; tagging, publication
177
+ and deployment require the platform workflow.
178
+
179
+ ### Fixed
180
+
181
+ - **A cell's commands no longer slice the value they sit on.** The boxes a
182
+ `Column.actions` cell reveals on hover had no backdrop of their own, so the
183
+ value under them ended mid-glyph — in the `Cell Commands` story the ID cell read
184
+ `S` and then two boxes. The overlay now fades into the cell's **own** tint
185
+ (`--pro-cell-overlay`: the row's wash at rest, the accent tint while the pointer
186
+ is on the cell), exactly the way the row's commands already faded into the row,
187
+ so a narrow column loses its value gradually instead of cutting it. The story
188
+ itself was demoing the feature in a 90px ID column while its two boxes measured
189
+ 52px; it now uses a 160px cell, where the value and both boxes read together
190
+ (the product's own ID column is 120px and carries one box).
191
+ - **The `Cell Commands` story named an icon the sprite does not have.** `copy`
192
+ is not in `ICONS`, and an unknown name draws an empty box — which is what the
193
+ screenshot showed. It uses `hashtag`, the glyph the demo's own "Copy ID"
194
+ affordance uses.
195
+
196
+ ### Fixed
197
+
198
+ - **A widget inside a cell keeps its own keys.** The grid's key listener sits on
199
+ the `<tr>`, so everything pressed inside a cell bubbled to it and the row acted
200
+ on it: a space in a rename field selected the row instead of typing a space, an
201
+ `Enter` on a `Column.actions` box opened the record (and the row's
202
+ `preventDefault` stopped the box from running at all), and an arrow key inside
203
+ an in-cell editor moved the cursor and pulled the focus out from under it,
204
+ committing the half-typed value. The row now answers only for the grid
205
+ (`src/components/table/keyboard.ts`): a key is the widget's when something
206
+ already handled it or when the focus is inside an `input`, `textarea`, `select`,
207
+ `button`, `a[href]`, `[contenteditable]` or one of the combobox / listbox /
208
+ textbox / slider / switch roles — a list of roles, not of this library's
209
+ classes, so a host's own editor inside a cell is treated the same way.
210
+ - **Focus follows the cursor in a grouped grid too.** `groupBy` renders one
211
+ `<tbody>` per group and the focus query only looked inside a single one, so ↑ ↓
212
+ moved the outlined cell while the keyboard stayed behind. The query now runs
213
+ over the whole scroll container, whichever body the cell is in.
214
+ - **The grid stops jumping while it loads.** The skeleton rows carried no pinned
215
+ geometry, so a grid with a frozen column drew its header frozen and its loading
216
+ rows unfrozen, then snapped sideways when the data landed. The skeletons wear
217
+ the same offsets as the rows they stand in for.
218
+ - **The frozen edge shadow is drawn once.** With `selectable` + `showIndex` + a
219
+ frozen column, the body drew the shadow on the index cell _and_ on the last
220
+ frozen data column while the header drew it once; the body now agrees with the
221
+ header (the shadow belongs to the outermost pinned cell of the run).
222
+ - **A group header spans the header tools column.** `headerTools` adds a column
223
+ to the header row, and the group row's `colSpan` did not count it, so the group
224
+ band stopped one column short (visible wherever a list groups _and_ shows the
225
+ column-settings gear).
226
+ - **A row keeps its announced position when it has a context menu.** The
227
+ `aria-rowindex` was added to the wrapper instead of the row, so every row of a
228
+ right-clickable grid — i.e. every `ListWorkbench` row — announced no position
229
+ at all. It is now set on the `<tr>` itself, which is also the menu's trigger.
230
+ - **`RichTextToolbar` is back in the published surface.** It is re-exported by
231
+ `src/ship/EntityDialog.tsx` rather than declared in it, and
232
+ `scripts/public-surface.mjs` only read declarations, so the name was missing
233
+ from `docs/api.md`, from the test-coverage check and from the story-coverage
234
+ check while being a real runtime export. The script now follows
235
+ `export * from` and `export { … } from` (the public surface keeps its 268 other
236
+ names unchanged).
237
+
238
+ ### Changed
239
+
240
+ - **`DataTable` is split by concern.** The 912-line `src/components/Table.tsx`
241
+ became `src/components/table/`: the props contract (`types`), the pinned-column
242
+ arithmetic and the skeleton geometry (`geometry`), the keyboard (`keyboard`),
243
+ the grouping (`grouping`), and the pieces the grid is assembled from —
244
+ `DataTable`, `TableHead`, `TableRow`, `SkeletonRows`, `BulkBar`, `ColumnMenu`,
245
+ `CellCommands`. `src/components/Table.tsx` stays as the barrel so every import
246
+ path (`../components/Table`, the stories, the tests, `src/index.ts`) is
247
+ unchanged, and `DataTableProps` stays next to `DataTable` because generated docs
248
+ resolve a component's props type in the component's own file.
249
+
250
+ ### Changed
251
+
252
+ - **The pointer works in two levels**, the product's own: the row it is in takes the
253
+ light wash (`--surface-table-row-hover`, with the pick cell's gutter following it)
254
+ and the cell under it takes a step deeper — the accent tint, which over that wash
255
+ lands on the reference's measured `#ebf0fb`. A hovered row still reads as a row and
256
+ the cell it points at reads as the target, instead of one lone cell lighting up in
257
+ a grid of unchanged rows.
258
+ - **A selected grid row is neutral, not blue.** Sampled off the reference: the
259
+ selected row is `#fafafa` while the accent stays on its checkbox (`#57abfb`), so
260
+ a selected row still reads as a row and the control carries the state. The grid
261
+ uses a new `--surface-table-row-selected` (the head's tone in both themes); the
262
+ accent-tinted `--surface-selected` is unchanged for everything else.
263
+ - The pick column wears the header's tone (`--surface-table-head`, `#fafafa`) like
264
+ a spreadsheet's row-header gutter, instead of the rows' white. A row carrying a
265
+ state of its own — hover, selection — still wins, so the gutter is never the odd
266
+ one out in its own row.
267
+ - **The grid is drawn as a grid.** The cells had a bottom border only, so the
268
+ columns were separated by whitespace and nothing but the frozen edge; every
269
+ column now carries the same hairline on its right (the filler and the structural
270
+ pick / action / tool cells included in the exclusion, since they are not
271
+ columns), which is what makes it read as a table.
272
+ - **The grid is a spreadsheet, not a list of rows.** Hovering lights up the cell
273
+ under the pointer (a light wash and a hairline) instead of washing the whole row,
274
+ and the keyboard cursor is a **cell**: ← → walk the columns, ↑ ↓ the rows,
275
+ Home/End jump to the ends of the row, Enter opens the record, Space toggles its
276
+ selection, and focus rides with the cursor on a roving tabindex — one tab stop
277
+ for the whole grid, which is the cursor cell. The arrow arithmetic moved out of
278
+ `useListCursor` (still exported) because a row index is no longer the thing being
279
+ moved.
280
+
281
+ ### Added
282
+
283
+ - **`Column.actions` — commands that live inside a cell.** Each column can carry
284
+ `[{ id, icon, label, onSelect(row) }]`: the boxes overlay the cell's right edge,
285
+ appear while the pointer is on **that cell** (or it holds focus), and each brings
286
+ its own tooltip and callback — the product's "Click to copy" on the identifier,
287
+ next to the value. The component owns the box, the reveal and the tooltip; the
288
+ host supplies the icon, the name and the write, which is all an integration needs.
289
+ - The **assignee cell's** person-add affordance: the host can name it
290
+ (`assignLabel(row)`) and take it over (`onAssign(row)`), or leave both out and let
291
+ the cell open its own people picker.
292
+
293
+ - `Toast` grew the things a host kept re-implementing: six **placements**
294
+ (`ToastProvider placement`, default unchanged at `top-center`), a **`warning`**
295
+ tone (the product's amber), an optional **title** with the message as its
296
+ description, one inline **action** (Undo / View / Retry) that does not dismiss
297
+ the toast itself, a **`filled`** variant on the tone's own colour, a
298
+ **`closeable`** switch, an **icon** override, and `max` to cap the stack.
299
+ `push` now returns the toast's id so a host can dismiss it early, and its third
300
+ argument takes an options object as well as the bare duration it took before.
301
+
302
+ ### Added
303
+
304
+ - **The selection bar is `DataTable`'s.** The product covers the grid's header row
305
+ with it while rows are selected, and the stylesheet was written for exactly that
306
+ (`.pro-selection-bar` is absolutely positioned, 50px, full width) — but only
307
+ `ListWorkbench` rendered one, above the table, so a `DataTable` on its own had no
308
+ bar at all. The table now renders it **in place of the header row**: the covered
309
+ header stands down (`inert`, and the select-all lives on the bar instead of
310
+ existing twice), the bar's box centres in the pick column and its count starts
311
+ where the first data column does, so nothing is off by a few pixels. `SelectionBar`
312
+ moved from the ship layer to `src/components/SelectionBar.tsx` (same public
313
+ export), and `buildBulkCommands` there turns the host's data into the bar the
314
+ table and the board both use.
315
+ - The grid keeps the column widths it was given: `table-layout: fixed` spreads the
316
+ leftover space over every column, so a 44px pick column came out 66px and nothing
317
+ could line up with it. A trailing auto-width filler column takes the slack.
318
+ - **The bulk bar is the component's.** `ListWorkbench` takes `bulk` — the data and
319
+ the write for Update status, Move in baseline, Schedule, Distribute workitems and
320
+ Edit properties — and builds the whole bar itself, in the product's order, above
321
+ whatever `bulkActions` adds and its own More (export / delete) and Cancel. The
322
+ round-robin spread, the confirmation message and the bulk edit dialog are the
323
+ library's; a page supplies choices and a write and nothing else. That is the
324
+ point of the exercise: a page should not re-implement a command the product
325
+ always shows.
326
+ - A lone command in `bulkActions` keeps its own label, icon and `onSelect`
327
+ instead of being folded into a submenu named after its id — which is what a bar
328
+ needs to mix grouped commands (Update status ›) with single ones (Distribute
329
+ workitems).
330
+ - **Frozen columns are part of the list view.** `ListView.frozen` names the
331
+ columns pinned to the left edge; `ListWorkbench` pins them (`fixed: 'left'`),
332
+ answers the column menu's Freeze / Unfreeze into that view state, and forwards
333
+ Move / Insert / Remove to the host, which owns `columns`. The demo's lists
334
+ freeze `id`, so the grid opens the way the product's does: the checkbox column
335
+ and the ID scroll together, the rest goes under them, and the frozen run carries
336
+ the edge shadow. The header ⋯ now works in the real list, not only in the
337
+ DataTable story.
338
+ - **`Menu` grows submenus.** An item may carry `items`: it renders a caret and
339
+ `aria-haspopup="menu"` / `aria-expanded`, opens those entries beside its own row
340
+ and keeps the parent open until something in the child is chosen (`ArrowRight`
341
+ opens it, `ArrowLeft` closes it and restores the focus). `divider: true` renders
342
+ the hairline `ContextMenuItem` already supported, so `Menu` and the context menu
343
+ finally agree on what an item is. `SelectionBar`'s hand-rolled submenu can move
344
+ onto this.
345
+ - **`DataTable`'s column menu** (`onColumnCommand`), the product's header ⋯:
346
+ Sort by (a real submenu — Ascending / Descending / Clear sort, the active
347
+ direction checked), Move left / Move right (disabled at the ends), Insert left /
348
+ Insert right, Freeze or Unfreeze (the pin reflects `column.fixed`) and Remove
349
+ this column. The library reports a `ColumnCommand` and reorders nothing itself —
350
+ the host owns `columns`. The story's harness applies every command, so the demo
351
+ moves, inserts, freezes and removes columns for real.
352
+ - `DataTable` gained the two things its grid was missing next to its stylesheet:
353
+ - **A row cursor** (`cursor`): one tab stop for the body, ↑ ↓ walking an
354
+ `is-cursor` row, Home / End jumping, Enter opening it, Space toggling its
355
+ selection, and a pointer click parking the cursor where it landed. It uses the
356
+ library's own `useListCursor`, which clamps the cursor when a filter shrinks
357
+ the list under it. `ListWorkbench` turns it on, so the product's list screen is
358
+ one tab stop instead of fifty.
359
+ - **The cursor row shows its checkbox.** The pick cell is "the row number at
360
+ rest, the checkbox on hover / selected / while a selection is active" — the
361
+ keyboard cursor is the pointer's hover, and it was missing from that list, so
362
+ the cursor row kept printing its number over an invisible checkbox. The number
363
+ now steps aside only when there _is_ a checkbox to take its place
364
+ (`:has(.pro-checkbox)`), so a host with no selection writer keeps its numbers.
365
+ - **Density** `'default' | 'compact'`: 36px rows and header with `--text-sm`
366
+ cells, and a reserved actions column instead of the floating overlay (that is
367
+ what `.pro-table__cell--actions`, until now dead, right-aligns).
368
+
369
+ ### Fixed
370
+
371
+ - **The row's commands sit at the row's end again.** The overlay resolved its
372
+ containing block against the actions cell — zero-width and `position: sticky`
373
+ whenever a column was frozen — so with a frozen column the pencil and the ⋯
374
+ landed at the **scrollport's** edge (mid-grid) instead of the row's. The cell
375
+ keeps the frozen edge's shadow and gives up the pinning, so the overlay's
376
+ containing block is the row itself: measured in the story, `offsetParent` is the
377
+ `TR` and the box sits 16px from the row's right edge.
378
+
379
+ - The pick cell's checkbox belongs to the **pick cell**. It used to appear as soon
380
+ as the pointer was anywhere in the row, so pointing at a title, a status or an
381
+ empty column offered a selection box the operator never asked for — the opposite
382
+ of the cell the interaction now belongs to. Only the pick cell reveals it; a
383
+ selected row, the cursor row and the bulk-selection mode keep theirs on screen,
384
+ because there the box is a state rather than an offer.
385
+
386
+ - The selection bar is exactly as tall as the header row it stands in for. It was
387
+ pinned at 50px while the grid's header measured 44px, so it hung 6px past the row
388
+ — visible as the `Cancel` button's box sticking out below the table's top edge.
389
+ Both now read one token (`--table-head-height`), so they cannot drift apart
390
+ again: measured in the story, the bar and the header row are the same 44px box
391
+ (40→84) with the first data row starting exactly at its bottom edge.
392
+
393
+ - A frozen column cannot look like a column of its own any more. The pinned cells
394
+ painted their own `--surface-default` and stayed in line with their row only
395
+ because the row states out-specified them (`tr:hover td` is 0,2,3 against
396
+ `td.is-fixed` at 0,2,1); any other row background — a host's own row class, a
397
+ state the stylesheet does not know — was covered by that opaque cell instead, and
398
+ a band that stops matching its row is what reads as an outlined column. The row
399
+ carries the background now and the pinned cells take `background: inherit`, so
400
+ the band is the row's colour by construction and still opaque for the columns
401
+ sliding under it.
402
+ - The pick column is centred. Its checkbox and its row number are two states of
403
+ one 44px slot, but the checkbox was laid out in the flow with `opacity: 0`, so
404
+ it took 16px + a gap and pushed the number off the axis — the header's
405
+ select-all sat 14px left of where the number was, and neither matched the
406
+ column. The checkbox is now absolutely centred and the cell aligns its content,
407
+ with the selector naming the element (`.pro-table td.pro-table__pick`) because
408
+ `.pro-table td` outranks a bare class. Measured on the built demo: every row's
409
+ number and box, and the header's box, are within 0px of the cell's centre.
410
+ - The pick cell no longer depends on `:has()` to hide its row number: the cell
411
+ says `is-selectable` when it really holds a checkbox. A browser without `:has()`
412
+ drops that whole rule, which left the checkbox drawn _next to_ the number.
413
+ - `DataTable` now does what its stylesheet already promised:
414
+ - **Only pin what is frozen.** The checkbox and actions columns were pinned
415
+ whenever the grid had a selection or row commands, so an unfrozen grid carried
416
+ a right-edge shadow with nothing to shadow and an opaque background on the
417
+ pick cell. They are pinned now only when a data column is (`column.fixed`).
418
+ - **Fixed columns work.** `.is-fixed-left` / `.is-fixed-right` and the two
419
+ `--shadow-table-fixed-*` tokens were dead CSS — nothing set the classes. A
420
+ column takes `fixed: 'left' | 'right'`, the component measures the offsets
421
+ from the preceding pinned widths, and the outer column of each run gets the
422
+ edge shadow. The checkbox and actions columns are pinned like the product's.
423
+ - **Group headers fold.** They drew a caret and did nothing; they are buttons
424
+ with `aria-expanded` now, uncontrolled (open) or controlled through
425
+ `expandedGroups` / `onExpandedGroupsChange`.
426
+ - **No dead controls.** The pick column keeps its row number, but its checkbox
427
+ (and the select-all box) only render when `onSelectedKeysChange` can write the
428
+ selection — the five host call sites that passed `selectable` without a
429
+ handler were showing checkboxes that did nothing. A `sortable` column whose
430
+ table has no `onSortChange` is disabled with a title instead of silently
431
+ ignoring clicks.
432
+ - `aria-rowcount` counts the header row as ARIA requires, and flat rows carry
433
+ `aria-rowindex`.
434
+ - Removed the unused `.pro-table__cell--compact` rule.
435
+
436
+ ### Fixed
437
+
438
+ - The focus ring is drawn once. `base.css`'s `.pro-root :focus-visible` (0,2,0)
439
+ out-specified the inline cell editors' own `outline: none` (0,1,0), so an open
440
+ cell showed the global 2px ring _and_ the cell's accent hairline — two
441
+ concentric boxes around the title. `.pro-cell-editor :focus-visible` now wins on
442
+ order, and `CONVENTIONS.md` records the specificity trap.
443
+ - The global focus rule no longer sets `border-radius`, which used to overrule a
444
+ component's own radius the moment it took focus (a focused button rendered 2px
445
+ instead of 4px). The ring follows the element's radius natively.
446
+
447
+ ### Changed
448
+
449
+ - `Tag` (and with it `StatusTag` and `CountTag`) is cut with the button's corner:
450
+ `border-radius: var(--radius)` instead of an 18px pill, and `LevelTag`'s badge
451
+ follows. A tag and a button are the same kind of object on the page, so they now
452
+ share the radius token. `Tag`'s `square` prop is gone — the button shape is the
453
+ default — and `pill` is the opt-in for the fully-rounded shape.
454
+
455
+ ### Added
456
+
457
+ - Storybook (`pnpm storybook`, `pnpm build:storybook`): the react-vite framework,
458
+ the docs, a11y and themes addons, a preview that loads the published
459
+ stylesheet, renders inside `.pro-root` and switches `data-theme` from the
460
+ toolbar. The args tables come from `react-docgen-typescript` reading the same
461
+ props declarations `docs/api.md` documents.
462
+ - `scripts/check-story-coverage.mjs`, wired into `pnpm verify`: every runtime
463
+ export has to be named by a `.stories.tsx`. The budget went 101 → 0, so all 113
464
+ exports are covered today (48 story files).
465
+
466
+ ## [0.2.0] — 2026-10-07
467
+
468
+ The release that makes `@stcn52/pro` a library you can consume rather than a
469
+ source tree you have to share: a repository, a test suite, a gate, generated
470
+ reference documentation and a package whose contents are checked.
471
+
472
+ ### Added
473
+
474
+ - **Repository** — a standalone git repository with `LICENSE` (MIT),
475
+ `.gitignore`, this changelog and `CONVENTIONS.md` (the authoring spec), plus
476
+ `engines`, `packageManager` and `files` in `package.json`.
477
+ - **Tests** — vitest + Testing Library + jsdom: 263 tests over 17 files covering
478
+ every one of the 113 exported components and hooks (rendering, controlled
479
+ values, the keyboard path, `Esc` and focus). `scripts/check-test-coverage.mjs`
480
+ enforces the claim: it reads the runtime exports out of `src/` and fails when
481
+ any of them is named by no test.
482
+ - **Static quality** — ESLint 10 flat config with the React hooks rules (16
483
+ known warnings, pinned with `--max-warnings`), and Prettier across the
484
+ repository.
485
+ - **`pnpm verify`** — one gate: package contract, typecheck, boundaries, test
486
+ coverage, docs, lint, format, tests, build, pack, `publint --strict`,
487
+ `are-the-types-wrong` and a pack smoke test that unpacks the tarball into a
488
+ throwaway consumer and imports the built ESM, the built CJS and the stylesheet
489
+ from there. Everything runs offline.
490
+ - **Boundary checks** — `scripts/check-boundaries.mjs` fails on any host symbol
491
+ in `src/` (repository name, router, storage, route literals, the demo store,
492
+ `app-*` class names) and on any host stylesheet rule whose subject is a
493
+ `pro-*` class. Every class the library renders must be `pro-*` (or an `is-*`
494
+ state hook).
495
+ - **Generated documentation** — `pnpm gen:docs` writes `docs/api.md` (every runtime
496
+ export with the props table of its props type, read from the TypeScript AST)
497
+ and `docs/tokens.md` (the token declarations, grouped as `tokens.css` groups
498
+ them, dark overrides apart). `scripts/check-docs.mjs` fails on a stale
499
+ generated file and on an export the README or `docs/components.md` does not
500
+ name.
501
+ - **`ListHeader`'s title is a real `<h2>`** (with `font: inherit`, so the
502
+ measured 15px/400 type is unchanged): it is the only title a tab page renders.
503
+
504
+ ### Changed
505
+
506
+ - `Field`'s generated id is handed to the control only (a component, or a
507
+ labellable native element) — injecting it into a `<span>` wrapper used to point
508
+ the label at something a label cannot name. `EntityDialog` names its field ids
509
+ explicitly.
510
+ - `Sidebar` follows a shell-level collapse: `SidebarCollapseProvider` wraps a
511
+ page tree once and every sidebar inside collapses with it, instead of a host
512
+ stylesheet hiding `.pro-sidebar`.
513
+ - `EntityDialog` no longer renders the host's `app-counter` / `app-input-wrap`
514
+ classes; the counter is the library's own `pro-input-counter` /
515
+ `pro-input-wrap`. `RichTextToolbar` and the rest of `EntityDialog`'s host
516
+ classes became `pro-richtext*` / `pro-dialog__*`, and the `@mention` highlight
517
+ became `.pro-mention` in the stylesheet.
518
+ - The narrow-screen rules that hid the sidebar (1024px) and the rail (640px)
519
+ live in the library now, not in the demo's stylesheet.
520
+ - `QuickStart` takes `done` / `total` for the checklist counter; `Tag` takes
521
+ `tone="accent"` and `size="sm"` for the quarter chip.
522
+ - The `New project` wizard's classes moved from the host's `proj-*` prefix into
523
+ the library's `pro-wizard__*` namespace.
524
+
525
+ ### Fixed
526
+
527
+ - `Menu`'s typeahead swallowed keystrokes typed into a searchable menu's search
528
+ field: it preventDefaulted any printable character that matched an item, so `d`
529
+ could not be entered in a list containing "Duplicate".
530
+ - `Input`'s `size?: 'md' | 'lg'` was intersected with the DOM's numeric `size`
531
+ attribute, which collapsed the prop to `undefined` for a typed caller.
532
+ - `TypeBadge` threw on a kind it does not know; it renders a neutral badge now.
533
+ - `Icon` returned nothing for an unknown name while the docs promised a warning
534
+ and an empty box; it warns and keeps the box.
535
+ - `Dialog` derived its title id from `Math.random()` during render (now
536
+ `useId()`); `Tree` carried two dead assignments; `ContextMenu`'s `useCallback`
537
+ missed the coordinates it reads; `PeoplePicker`'s effect missed `setCursor`;
538
+ `Toast` kept a stale `eslint-disable`.
539
+ - `exports["."]` pointed the `require` condition at the ESM type declarations;
540
+ `import` and `require` carry their own `types` (`index.d.ts` / `index.d.cts`).
541
+
542
+ ### Notes
543
+
544
+ - Still 0.x: the demo is the only consumer, and 1.0.0 is for the point where the
545
+ API is frozen for a second one.
546
+ - `docs/measurements.md` keeps recording where each measurement came from.
547
+
548
+ ## [0.1.0] — 2026-10-07
549
+
550
+ The first cut: the Ship workbench restored as a library, then the demo's
551
+ components pulled out of the demo.
552
+
553
+ ### Added
554
+
555
+ - **Foundations** — `cx`, the `Intl`-backed formatters (`formatNumber`,
556
+ `formatListTime`, `formatDateTime`, `formatCompact`, `pluralize`),
557
+ `useControllableState`, `statusColor`, `avatarColor`, `initials`, `nextRuleId`.
558
+ - **Tokens and styles** — `tokens.css` (raw scale + purpose-named semantic
559
+ tokens, light and dark), `base.css`, `primitives.css`, `ship.css`, published
560
+ together as `styles.css` and separately as `tokens.css`.
561
+ - **Icons** — `Icon`, `ICONS`, `IconName`: 146 glyphs taken verbatim from the
562
+ product's sprite.
563
+ - **Primitives** — `Button`, `SplitButton`, `ActionButton`, `Input`, `Textarea`,
564
+ `SearchInput`, `Field`, `Checkbox`, `Switch`, `Select`, `MultiSelect`,
565
+ `Popover`, `Menu`, `ContextMenu`, `Tooltip`, `Dialog`, `Toast` /
566
+ `ToastProvider` / `useToast`, `DataTable`, `Pagination`, `Tag` / `StatusTag` /
567
+ `LevelTag` / `CountTag`, `Avatar` / `AvatarStack`, `Progress`, `Metric`,
568
+ `BarChart`, `Donut`, `Sparkline`, `ScatterPlot`, `Crumbs`, `KeyValue`, `Card`,
569
+ `Nav`, `Tree` / `TreeGroup`, `Sidebar`, `Segment`, `Chip`, `Divider`,
570
+ `EmptyState`, `ErrorState`, `Skeleton`, `TableSkeleton`, `LoadingBlock`,
571
+ `InlineSpinner`, `Banner`.
572
+ - **Ship surface** — `AppRail`, `AppHeader`, `ProductHeader`, `HeaderActions`,
573
+ `BrandMark`, `ListHeader`, `ListToolbar`, `FilterPanel`, `FilterChip`,
574
+ `BoardView`, `RoadmapView`, `DocSplit`, `TitleCell`, `TypeBadge`, `ProductCell`,
575
+ `StarButton`, `QuickStart`, `TableBanner`, `SelectionBar`, `VoteCount`,
576
+ `DetailSheet` / `DetailSection` / `DetailField` / `Feed` / `FeedFilter` /
577
+ `CommentComposer`.
578
+ - **Composites extracted from the demo** — `ListWorkbench`, `CommentThread`,
579
+ `AttachmentUpload`, `LinkPicker`, `FilePreview`, `TransitionsTimeline`,
580
+ `EntityDialog`, `EntityPicker`, `ShareDialog`, `ReportCanvas`, `RoadmapEditor`,
581
+ `ProjectWizard`, `DetailBlock`, `DetailTool`, `EditableText`, `AccountMenu`,
582
+ `ShortcutsDialog`, `QuickStartDialog`.
583
+ - **Theming** — `data-theme="light" | "dark" | "auto"` on any ancestor;
584
+ components only read CSS variables.
585
+
586
+ ### Changed
587
+
588
+ - `EntityDialog` no longer renders the host's `app-counter` / `app-input-wrap`
589
+ classes; the counter is the library's own `pro-input-counter` /
590
+ `pro-input-wrap`.
591
+ - `QuickStart` takes `done` / `total` for the checklist counter; `Tag` takes
592
+ `tone="accent"` and `size="sm"` for the quarter chip.
593
+ - The `New project` wizard's classes moved from the host's `proj-*` prefix into
594
+ the library's `pro-wizard__*` namespace.
595
+
596
+ - Add general Empty, Spin and Result feedback entries; extend Skeleton with
597
+ compound placeholders and content switching, cancellable loading delay,
598
+ localized descriptions, inert busy content and reduced-motion handling.
599
+
600
+ - Extend Slider with native double range handles, marks, vertical layout, step
601
+ normalization, tooltips and completed interaction events; extend Rate with
602
+ half-star ratings, configurable count, hover feedback and custom characters.
603
+
604
+ - Extend Progress with circle/dashboard, segmented steps, percent/status,
605
+ success overlays, formatted information and logical dashboard gaps in RTL.
606
+
607
+ - Extend Tabs with placements, RTL keys, editable cards, dynamic selection and
608
+ close-focus recovery; add Collapse header keys/extra actions/lifecycle variants
609
+ and Steps item statuses, offsets, localized text and provider-disabled support.
610
+
611
+ - Add standalone Calendar and Timeline with ISO date selection, month/year views, keyboard/RTL navigation, controlled data, custom cells, pending items and logical layouts.
612
+
613
+ - Add List/List.Item.Meta, grouped Listy with fixed-height virtualization and scroll refs, and measured responsive Masonry.
614
+
615
+ - Add Affix, Anchor, FloatButton/Group and shared BackTop with custom scroll containers, logical placement, progress and reduced-motion support.