@stcn52/pro 0.0.0-stage → 0.2.1

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 +621 -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 +23272 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.d.cts +5068 -0
  10. package/dist/index.d.ts +5068 -0
  11. package/dist/index.js +23060 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/styles.css +10485 -0
  14. package/dist/tokens.css +322 -0
  15. package/docs/antd-alignment-plan.md +983 -0
  16. package/docs/api.md +3669 -0
  17. package/docs/components.md +1706 -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 +95 -4
package/CONVENTIONS.md ADDED
@@ -0,0 +1,152 @@
1
+ # Component authoring conventions
2
+
3
+ `@stcn52/pro` is a component library, not a demo. Everything in it must be
4
+ reasonable to ship to a host application that knows nothing about PingCode Ship,
5
+ the demo store or the demo's routes. This file is the definition of done for a
6
+ component; `pnpm verify` is the machine check behind it.
7
+
8
+ ## What the library is
9
+
10
+ A 1:1 restoration of the PingCode **Ship** workbench, published as tokens, CSS
11
+ layers and React components. Styling is **plain CSS classes driven by design
12
+ tokens** — no CSS-in-JS, no per-component stylesheet files, no inline geometry.
13
+
14
+ ```
15
+ src/styles/tokens.css raw scale + purpose-named semantic tokens (light/dark)
16
+ src/styles/base.css reset, type scale, utilities
17
+ src/styles/primitives.css controls, overlays, table, navigation, states, charts
18
+ src/styles/ship.css the Ship surface: rail, headers, toolbar, detail sheet,
19
+ list workbench, wizard, detail blocks
20
+ src/components/*.tsx primitives (one file per component family)
21
+ src/components/table/ a family that outgrew one file: the DataTable parts,
22
+ re-exported unchanged by src/components/Table.tsx
23
+ src/ship/*.tsx product chrome and the extracted composites
24
+ src/index.ts the only barrel: every public name is re-exported here
25
+ ```
26
+
27
+ ## Rules
28
+
29
+ 1. **Tokens only.** Colours, spacing, radii, type and durations come from
30
+ `tokens.css`. A new literal needs a reason in a comment next to it.
31
+ 2. **Purpose-named colour.** `--surface-*`, `--fg-*`, `--border-*`, `--accent`,
32
+ `--status-*`. The raw `--gray-*` scale exists only underneath them.
33
+ 3. **One stylesheet per layer.** A new component adds its rules to the layer it
34
+ belongs to, in the same order as the barrel, not to a new file. Element
35
+ resets are written with `:where()` so they carry zero specificity.
36
+ 4. **Class naming is `pro-<block>__<element>--<modifier>`.** A class that
37
+ describes a _layout slot_ (`pro-row`, `pro-num`, `pro-detail__tools`) may be
38
+ used by a host; anything else is internal and a host should get a component
39
+ instead. Never add an `app-*` class: that prefix belongs to host applications.
40
+ 5. **No host knowledge.** The library must not contain a route string
41
+ (`/ship/...`, `/pjm/...`), a store, a `localStorage` key, a demo id or a demo
42
+ name. Data arrives as props; navigation arrives as callbacks.
43
+ 6. **Controlled by default where it matters.** Anything with a selection takes
44
+ `value` + `onChange`; use `useControllableState` so a component also works
45
+ uncontrolled (`defaultValue`, `defaultOpen`, `defaultExpanded`).
46
+ 7. **Refs are forwarded** on every form control (focus management is the host's
47
+ job, and `⌘K`-style shortcuts depend on it).
48
+ 8. **The five states are structural.** Anything that shows data accepts
49
+ `status="loading" | "error" | "ready"` plus `emptyState` / `errorState`, so no
50
+ screen can ship with only the populated case.
51
+ 9. **Keyboard first.** One focus ring (`:focus-visible` in `base.css`), `Esc`
52
+ closes every floating layer, arrows move through lists, `Enter`/`Space`
53
+ activate, focus returns to the element that opened a layer, and dialogs trap
54
+ `Tab` inside themselves.
55
+ 10. **Accessibility is not optional.** Every control has a label; an icon-only
56
+ button takes `label` (becomes `aria-label` + `title`); decorative icons are
57
+ `aria-hidden`; live regions exist before content arrives; motion is disabled
58
+ under `prefers-reduced-motion`.
59
+ 11. **Export discipline.** Named exports only, no default exports, types exported
60
+ next to the component, and every public name re-exported from
61
+ `src/index.ts`. Adding an export means updating the README table and
62
+ `docs/components.md` in the same change.
63
+ 12. **Every exported component has a test** under `src/__tests__/<Name>.test.tsx`
64
+ covering, at minimum: it renders; a controlled prop is honoured; the keyboard
65
+ path works; and `Esc`/focus behaviour where the component has a floating
66
+ layer.
67
+ 13. **Semantic versioning.** A user-visible change adds a CHANGELOG entry under
68
+ `## [Unreleased]`; breaking a prop, a default or an exported name is a major
69
+ bump and needs a migration note.
70
+
71
+ ## Documentation
72
+
73
+ `docs/api.md` and `docs/tokens.md` are **generated** from `src/` — run `pnpm gen:docs`
74
+ after touching a component, a prop or a token. `pnpm verify` regenerates them and
75
+ fails on any difference, so the committed reference cannot drift from the code.
76
+
77
+ The prose is hand-written and checked the other way round: every runtime export
78
+ must be named in `README.md`, and every component in `docs/components.md`. Adding
79
+ an export means adding it to both.
80
+
81
+ ## Focus
82
+
83
+ `base.css` draws the focus ring for everything inside `.pro-root` /
84
+ `.pro-portal` with `.pro-root :focus-visible` (**0,2,0**). A component that paints
85
+ its own focus indicator — the open cell editors, whose accent hairline _is_ the
86
+ field — has to out-specify that rule: name the component, not the bare input
87
+ (`.pro-cell-editor :focus-visible`, not `.pro-quick-text__input { outline: none }`,
88
+ which is only 0,1,0 and loses). Two rings around one field is the symptom.
89
+
90
+ ## Grid cells
91
+
92
+ `.pro-table th, .pro-table td { text-align: left; … }` is one class **plus an
93
+ element**, so a bare `.pro-table__pick { text-align: center }` loses to it. A rule
94
+ that aligns or states a table cell has to name the element too
95
+ (`.pro-table td.pro-table__pick`). The same applies to the pick cell's two states:
96
+ the checkbox is taken out of the flow and centred, so the invisible one cannot
97
+ push the row number off the axis the header's select-all sits on.
98
+
99
+ ## Stories
100
+
101
+ Every exported component gets a story, next to its source
102
+ (`src/components/Button.stories.tsx`), under a `Components/<Group>/<Name>` or
103
+ `Ship/<Group>/<Name>` title. A story set is expected to show the states a host
104
+ will actually meet — the five list states, controlled and uncontrolled, the
105
+ keyboard path, an open floating layer — not just the happy one. `pnpm verify`
106
+ fails when an export has no story (`scripts/check-story-coverage.mjs`), and both
107
+ ESLint and Prettier cover the story files.
108
+
109
+ ## Frozen columns
110
+
111
+ A pinned cell has to be opaque, or the columns sliding under it show through — but
112
+ it must never look like a column of its own. The **row** carries the state
113
+ background (`tr:hover`, `tr.is-selected`, `tr.is-cursor`, a host's own class) and
114
+ `td.is-fixed` takes `background: inherit`. A pinned cell that paints a colour of
115
+ its own is one row-state away from outlining itself.
116
+
117
+ ## Splitting a component family
118
+
119
+ One file per family is the default, and most families stay one file. When one
120
+ grows past what a reader can hold — `DataTable` reached 912 lines — it becomes a
121
+ directory (`src/components/table/`) of modules cut by **what changes together**:
122
+ the public contract (`types`), the arithmetic (`geometry`), the keyboard
123
+ (`keyboard`), the grouping (`grouping`), and one module per thing the component
124
+ renders (`DataTable`, `TableHead`, `TableRow`, `SkeletonRows`, `BulkBar`,
125
+ `ColumnMenu`, `CellCommands`).
126
+
127
+ Two rules keep that readable and keep the tooling honest:
128
+
129
+ - **The public path stays where it was.** `src/components/Table.tsx` remains the
130
+ barrel (`export * from './table/types'` and `'./table/DataTable'`), so no host
131
+ and no story has to learn a new import. `src/index.ts` is unchanged.
132
+ - **The props type stays next to the component.** `scripts/gen-docs.mjs` resolves
133
+ `DataTableProps` **in the same file** as `DataTable`, so moving the type to a
134
+ separate module would silently empty the generated props table — which is also
135
+ why `scripts/public-surface.mjs` follows `export * from` rather than only
136
+ reading declarations: without that, every name behind a barrel would drop out
137
+ of `docs/api.md` and out of the test/story coverage checks.
138
+
139
+ ## Working on it
140
+
141
+ ```bash
142
+ pnpm typecheck # tsc --noEmit
143
+ pnpm lint # eslint
144
+ pnpm test # vitest run
145
+ pnpm build # tsup (ESM + CJS + d.ts) then scripts/build-styles.mjs
146
+ pnpm verify # everything above, plus publint/attw and a pack smoke test
147
+ ```
148
+
149
+ `pnpm verify` is the gate: a change is done when it passes, and the docs and
150
+ CHANGELOG are updated in the same change.
151
+
152
+ React ref access and state-in-effect checks are errors. `pnpm verify` permits zero lint warnings; fix the cause rather than disabling a rule. Stable controlled setters publish committed props before descendant layout effects.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Klun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,227 @@
1
- # Temporary Holding Version
1
+ # @stcn52/pro
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A 1:1 restoration of the PingCode **Ship** workbench as a publishable React
4
+ component library: design tokens, primitives and the Ship product chrome, with
5
+ light and dark themes.
6
+
7
+ ```
8
+ src/styles/tokens.css raw PingCode scale + purpose-named semantic tokens
9
+ src/styles/base.css reset, type scale, utilities
10
+ src/components/* primitives (button, input, table, tree, overlay, charts…)
11
+ src/ship/* product chrome (rail, headers, toolbar, entity views)
12
+ src/icons/icons.ts 146 glyphs taken verbatim from PingCode's icon sprite
13
+ ```
14
+
15
+ ## Install and use
16
+
17
+ ```bash
18
+ pnpm add @stcn52/pro react react-dom
19
+ ```
20
+
21
+ ```tsx
22
+ import { AppRail, ListToolbar, DataTable, StatusTag } from '@stcn52/pro';
23
+ import '@stcn52/pro/styles.css'; // or '@stcn52/pro/tokens.css' for tokens only
24
+
25
+ export function Screen() {
26
+ return (
27
+ <div className="pro-root">
28
+ <StatusTag status="Pending" />
29
+ </div>
30
+ );
31
+ }
32
+ ```
33
+
34
+ Every component is a named export from the package root. The stylesheet is a
35
+ single file; the token layer is also published separately so a host application
36
+ can adopt the scale without the component styles.
37
+
38
+ ### Consuming a local checkout
39
+
40
+ A host next to this repository depends on it with pnpm's `link:` protocol, so
41
+ imports resolve through the package's `exports` map into `dist/`:
42
+
43
+ ```json
44
+ { "dependencies": { "@stcn52/pro": "link:../klun-pro" } }
45
+ ```
46
+
47
+ `file:` also works, but pnpm snapshots the directory at install time: a later
48
+ `pnpm build` here would not reach the host until it installs again, and the host
49
+ would quietly run a stale library. `link:` keeps the package live, and the host
50
+ still consumes the built artefact rather than the source.
51
+
52
+ ## Storybook
53
+
54
+ Every component has a story, and the story is where to look first when a prop's
55
+ behaviour is not obvious from its name:
56
+
57
+ ```bash
58
+ pnpm storybook # http://localhost:6006
59
+ pnpm build:storybook # static site in dist-storybook/
60
+ ```
61
+
62
+ The preview loads the same stylesheet the package publishes
63
+ (`src/styles/index.css`), renders each story inside `.pro-root` — where the
64
+ library's element resets live — and puts a light/dark switch in the toolbar that
65
+ sets `data-theme` on the frame. The docs addon reads the exported props types
66
+ with `react-docgen-typescript`, so an args table is generated from the same
67
+ declarations `docs/api.md` is generated from.
68
+
69
+ `scripts/check-story-coverage.mjs` runs inside `pnpm verify`: every runtime
70
+ export has to be named by a `*.stories.tsx`, with a budget that only goes down.
71
+
72
+ ## Theming
73
+
74
+ Theme is selected with `data-theme` on any ancestor — usually `<html>`:
75
+
76
+ ```html
77
+ <html data-theme="light">
78
+ <!-- or "dark" -->
79
+ <html data-theme="auto">
80
+ <!-- follows prefers-color-scheme -->
81
+ </html>
82
+ </html>
83
+ ```
84
+
85
+ Components never branch on colour scheme; they only read CSS variables.
86
+
87
+ ## What is in the box
88
+
89
+ | Group | Exports |
90
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
91
+ | Foundations | `cx`, `formatNumber`, `formatCount`, `formatDay`, `formatListTime`, `formatDateTime`, `formatCompact`, `pluralize`, `statusColor`, `avatarColor`, `initials`, `useControllableState` |
92
+ | Icons | `Icon`, `ICONS`, `IconName` |
93
+ | Actions | `Button`, `SplitButton`, `ActionButton` |
94
+ | Forms | `Input`, `Textarea`, `SearchInput`, `Field`, `Checkbox`, `Switch`, `Select`, `MultiSelect` |
95
+ | Overlays | `Popover`, `Menu`, `Tooltip`, `Dialog`, `ContextMenu` / `ContextMenuList` / `useContextMenu`, `useToast` / `ToastProvider`, `usePopoverClose`, `useAnchorRef` |
96
+ | Data | `DataTable` (`Column`, `SortState`), `Pagination`, `Tag` / `StatusTag` / `LevelTag` / `CountTag`, `Avatar` / `AvatarStack` / `AvatarPlaceholder` / `IconAvatar`, `Progress`, `Metric`, `BarChart`, `Donut`, `Sparkline`, `ScatterPlot`, `Crumbs`, `KeyValue`, `Card` |
97
+ | Navigation | `Nav`, `Tree` / `TreeGroup`, `Sidebar` / `SidebarCollapseProvider` / `useSidebarCollapsed`, `Segment`, `Chip`, `Divider` |
98
+ | States | `Empty`, `Spin`, `Result`, `EmptyState`, `ErrorState`, `EmptyArt`, `Skeleton`, `TableSkeleton`, `LoadingBlock`, `InlineSpinner`, `Banner` |
99
+ | Ship chrome | `AppRail`, `AppHeader`, `ProductHeader`, `HeaderActions`, `BrandMark`, `ListHeader`, `ListToolbar`, `FilterPanel`, `FilterChip`, `BoardView`, `RoadmapView`, `DocSplit`, `TitleCell`, `TypeBadge`, `ProductCell`, `StarButton`, `QuickStart`, `TableBanner`, `SelectionBar`, `VoteCount` |
100
+ | Entity surfaces | `DetailSheet`, `DetailBlock`, `DetailTool`, `DetailSection`, `DetailField`, `Feed`, `FeedFilter`, `CommentComposer`, `EditableText` |
101
+ | Inline editors | `PeoplePicker` (`PeoplePickerTab`), `QuickSelect`, `QuickText`, `useSelectAnchor`, `useListCursor` |
102
+ | Assistant | `AiPanel`, `PingMark` |
103
+ | Shell surfaces | `AccountMenu`, `ShortcutsDialog`, `QuickStartDialog` |
104
+ | Canonical data | `DEFAULT_SHARING` (`ReportSharing`), `defaultCanvasWidgets` / `isCanvasWidgetSpan`, `componentLine` / `primaryComponents`, `quarterWeekendDays`, `cursorAfter` / `matchesQuery`, `downloadAttachment` / `exportRowsToCsv` |
105
+ | Composites | `ListWorkbench`, `EntityPicker`, `EntityDialog`, `ProjectWizard`, `CommentThread`, `AttachmentUpload`, `LinkPicker`, `FilePreview`, `TransitionsTimeline`, `ShareDialog`, `ReportCanvas`, `RoadmapEditor`, `RichTextToolbar` | |
106
+
107
+ ## Design rules the code follows
108
+
109
+ - **Tokens over literals.** Colours, spacing, radii and type come from
110
+ `tokens.css`; a new literal needs a reason. Element resets are written with
111
+ `:where()` so they carry zero specificity and never beat a component class.
112
+ - **Purpose-named colour.** `--surface-*`, `--fg-*`, `--border-*`, `--accent`,
113
+ `--status-*` — the raw `--gray-*` scale exists only underneath them.
114
+ - **The five states are real.** `DataTable` takes `status="loading" | "error" |
115
+ "ready"` plus `emptyState` / `errorState` nodes, so no list can ship with only
116
+ the populated case.
117
+ - **Keyboard first.** One focus ring style, `Esc` closes every floating layer,
118
+ `Dialog` traps Tab inside the sheet, `Tree` and the rail expose
119
+ `aria-current`, table headers expose `aria-sort`, and a live region announces
120
+ row counts.
121
+ - **Motion is small and optional.** 120–180 ms transitions, all of them
122
+ disabled under `prefers-reduced-motion`.
123
+
124
+ ## Build
125
+
126
+ ```bash
127
+ pnpm install
128
+ pnpm build # tsup (ESM + CJS + .d.ts) then scripts/build-styles.mjs
129
+ pnpm typecheck
130
+ pnpm gen:icons <path-to-icons-common-full.json> # regenerates src/icons/icons.ts
131
+ ```
132
+
133
+ `pnpm build` writes `dist/index.{js,cjs,d.ts}`, `dist/styles.css` and
134
+ `dist/tokens.css`.
135
+
136
+ ## Fidelity
137
+
138
+ `docs/measurements.md` records where every measurement came from (live DOM
139
+ probes, pixel sampling, and PingCode's own stylesheets) and lists the known
140
+ gaps — the most important being that four Ship tabs were captured while their
141
+ grid was still a loading skeleton, so their column sets come from the DOM rather
142
+ than from pixels, and that no dark-theme screenshot of the running product was
143
+ obtainable, so dark mode is built from PingCode's own `:root[theme=dark]`
144
+ token block.
145
+
146
+ ## Additional common components
147
+
148
+ `Radio` / `RadioGroup`, `Tabs`, `Collapse`, `Badge`, `Slider`, `Steps`, `Alert`, `CheckboxGroup`, `PasswordInput`, `Rate`, `Cascader`, `Transfer`, `DatePicker`, and `DateRangePicker` complement the Ship primitives.
149
+ Their option-based APIs and behaviour are informed by [Ant Design](https://github.com/ant-design/ant-design), implemented with native controls and the existing tokens; no antd runtime dependency is required.
150
+ Tree/DirectoryTree include cached directory ranges, RTL navigation, leaf icons and
151
+ source-aligned drop geometry; see the onDrop position migration in `docs/components.md`.
152
+
153
+ Cascader supports multiple parent/leaf paths, intermediate selection, field mapping,
154
+ lazy children with retry and controlled opening/search.
155
+
156
+ Selection components support controlled and uncontrolled state. Transfer also supports
157
+ independent controlled checks, directional moves, per-side paging and custom lists. See Storybook and `docs/components.md`.
158
+
159
+ Releases and deployments use the platform workflow (build → approval → publish →
160
+ deploy). See [RELEASING.md](./RELEASING.md); local release commands validate only.
161
+
162
+ `Tree` now supports controlled expansion/selection/checking, lazy loading,
163
+ search highlighting, drag-and-drop and fixed-height virtual scrolling.
164
+ `DirectoryTree` adds file-browser Ctrl/Meta/Shift selection and click/double-click expansion.
165
+
166
+ ### Global configuration and forms
167
+
168
+ `ConfigProvider` supplies nested `locale` (`en-US` / `zh-CN`), `direction` and
169
+ `disabled` defaults. Explicit control props win. `useProConfig` and
170
+ `useComponentDisabled` expose these defaults to host controls.
171
+
172
+ `Form`, `FormItem`, `FormList`, `useForm`, `useFormInstance` and `useWatch` provide
173
+ nested field state, dynamic arrays, validation, resets and async submission.
174
+ `Form.Item`, `Form.List` and the compound hooks are also available. Full Ant
175
+ Design API compatibility is not implemented. See [component reference](docs/components.md).
176
+
177
+ Select and MultiSelect support grouped options, labeled values, clearing, custom rendering,
178
+ controlled popups, async states, custom/remote search and opt-in virtual scrolling.
179
+ MultiSelect also supports tags, token separators, and selection limits; see
180
+ [component contracts](docs/components.md#select--multiselect).
181
+
182
+ 全库完善的待办、优先级和验收标准见[AntD 对照计划](docs/antd-alignment-plan.md)。
183
+
184
+ Common input additions: `InputNumber` (number/null), `AutoComplete` (editable suggestions),
185
+ `TreeSelect` (hierarchical single/multiple/check selection) and `TimePicker` (local ISO clock).
186
+ They integrate with Form and ConfigProvider; see the component guide for native API differences.
187
+
188
+ General display entries: `Breadcrumb`, responsive `Descriptions`, formatted `Statistic`,
189
+ and `Typography` with Text/Title/Paragraph/Link, copying, editing and CSS ellipsis.
190
+
191
+ General layout entries: `Layout` (Header/Content/Footer/Sider), `Row`/`Col` (24-column
192
+ responsive grid), `Grid.useBreakpoint`, `Flex`, `Space`/Compact and `Splitter`/Panel.
193
+
194
+ `Dropdown` combines a native Button trigger with `Menu`; `Popconfirm` adds controlled opening,
195
+ async confirmation, cancellation and retry feedback using the existing Popover.
196
+
197
+ `Drawer` shares Dialog's modal stack, focus restoration and body scroll lock, with four physical
198
+ edge placements, bounded width/height and independent keyboard/mask/close-button controls.
199
+
200
+ `Image` renders actual image bytes with native refs, fallback/loading content and controlled
201
+ Dialog previews; `Image.PreviewGroup` navigates an explicit `items` list.
202
+
203
+ `Upload` keeps real File objects, supports manual/preflight uploads and explicit XHR `action`
204
+ or cancellable `customRequest`, controlled lists, accept/count limits and drag/drop.
205
+
206
+ `App` hosts separate message and notification stacks. Use `App.useApp()` for the nearest context;
207
+ exported `message`/`notification` use the last registered App and restore the prior host on unmount.
208
+
209
+ Standalone Calendar and Timeline provide event calendars and chronological lists without Ship data dependencies.
210
+
211
+ List (with ListItem and ListItemMeta), Listy and Masonry provide paginated lists, grouped fixed-height virtual lists, and measured responsive masonry layouts.
212
+
213
+ Affix, Anchor, FloatButton (with FloatButtonGroup) and BackTop support scroll navigation and floating actions.
214
+
215
+ Mentions provides native textarea suggestions; ColorPicker provides validated solid/gradient color editing, formats, alpha and presets.
216
+
217
+ Carousel, Tour, QRCode, Watermark and BorderBeam add media navigation, guided steps, real QR encoding, repeated marks and perimeter decoration.
218
+
219
+ DataTable supports hierarchical rows, grouped headers, multi-column sorting, radio selection and fixed-height virtual windows; see the component guide for summary scope and full-render fallbacks.
220
+
221
+ DatePicker supports ISO periods, local datetime confirmation, multiple dates, lazy presets and strict display formats; DateRangePicker shares date/time constraints and atomic tuple presets.
222
+
223
+ ConfigProvider supports nested `locale`, `direction`, `disabled`, `theme` and Klun CSS `tokens`; portalled overlays retain this configuration. See [configuration behavior](docs/components.md).
224
+
225
+ Avatar supports numeric sizes, square shapes and measured text scaling; AvatarStack names hidden members in its overflow marker. See [component contracts](docs/components.md).
226
+
227
+ Card exposes `Card.Grid` / `Card.Meta` (also `CardGrid` / `CardMeta`) for responsive content composition.
package/RELEASING.md ADDED
@@ -0,0 +1,51 @@
1
+ # Releasing
2
+
3
+ All releases and deployments must run through the Klun platform workflow:
4
+ **build → approval → publish → deploy**. Local commands are for validation and
5
+ artifact inspection. Never replace the workflow with `kc deploy`, a direct local
6
+ npm publish, or manual cluster changes. If a workflow fails, fix it and rerun it.
7
+
8
+ ## Prepare the change
9
+
10
+ 1. Commit the code, tests, generated docs and release notes.
11
+ 2. Choose a version: patch for compatible fixes, minor for additive components or
12
+ props, major for breaking API changes. While 0.x, a breaking minor still needs
13
+ an explicit migration note.
14
+ 3. Update `package.json` and move the applicable `CHANGELOG.md` entries from
15
+ `Unreleased` into `## [x.y.z] — YYYY-MM-DD`.
16
+ 4. Run `pnpm verify` and `pnpm build:storybook` locally. For an already dated
17
+ version, `pnpm release x.y.z --dry-run` performs local validation only. It does
18
+ not commit, tag, publish, deploy, or call the platform.
19
+
20
+ ## Platform workflow
21
+
22
+ Configure the workflow on the platform for this repository and environment.
23
+ The repository does not contain an environment-specific platform workflow ID or
24
+ registry credentials; those must come from the platform configuration.
25
+
26
+ | Stage | Required behavior |
27
+ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28
+ | Build | Check out the selected commit on a connected build runner. Install with `pnpm install --frozen-lockfile`, then run `pnpm verify` and `pnpm build:storybook`. Store the npm tarball, Storybook bundle and check results as run artifacts. |
29
+ | Approval | Review the exact commit, version, release notes, validation results and artifact before allowing publication. |
30
+ | Publish | Publish the approved artifact to the registry configured on the platform, using platform-managed credentials. Record its version, checksum and source commit; create the release tag through this workflow. |
31
+ | Deploy | Deploy the approved Storybook artifact or consuming application through the workflow when there is a deployment target. An npm package has no cluster deployment of its own; record that stage as not applicable when only the package is released. |
32
+
33
+ Runner selection is declared through the platform's build-runner node and its
34
+ connections. Approval must precede publication and deployment. Retrying uses the
35
+ same reviewed commit; a different commit requires a new reviewed run.
36
+
37
+ ## Local safeguards
38
+
39
+ `pnpm release` rejects invocations without `--dry-run`. The script only validates;
40
+ it contains no commit, tag or publication path. `pnpm pack` is safe for inspecting
41
+ a local artifact. `prepublishOnly` runs `pnpm verify` as an additional package
42
+ check; it cannot authenticate platform approval, so approval enforcement belongs
43
+ to the platform and its registry credentials.
44
+
45
+ ## Recovery
46
+
47
+ Repair failed workflow steps and rerun the workflow. Roll back a deployed site or
48
+ consumer by selecting its prior approved artifact in the platform workflow. Do
49
+ not overwrite an existing npm version; publish a new corrected version through
50
+ a new approved run. Keep the run ID, approval, logs and artifact checksums with
51
+ the release record.
@@ -0,0 +1,52 @@
1
+ # Third-party notices
2
+
3
+ @rc-component/qrcode 2.0.0 is bundled for SVG/canvas QR encoding.
4
+
5
+ The MIT License (MIT)
6
+ Copyright (c) 2015-present Alipay.com, https://www.alipay.com/
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ The bundled QR Code generator also carries Copyright (c) Project Nayuki (MIT License).
27
+ The MIT permission and disclaimer above apply to that code.
28
+
29
+ ## @babel/runtime helpers
30
+
31
+ MIT License
32
+
33
+ Copyright (c) 2014-present Sebastian McKenzie and other contributors
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining
36
+ a copy of this software and associated documentation files (the
37
+ "Software"), to deal in the Software without restriction, including
38
+ without limitation the rights to use, copy, modify, merge, publish,
39
+ distribute, sublicense, and/or sell copies of the Software, and to
40
+ permit persons to whom the Software is furnished to do so, subject to
41
+ the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be
44
+ included in all copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
50
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
51
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
52
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.