@cyberskill/design 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +1 -1
- package/README.md +4 -4
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/_ds_bundle.js +2 -2
- package/_esm/cs.mjs +2 -2
- package/docs/contrast-report.md +1 -1
- package/docs/conventions.md +2 -2
- package/docs/quality-gates.md +1 -1
- package/docs/release-notes.md +1 -1
- package/docs/vi/contrast-report.md +1 -1
- package/docs/vi/conventions.md +2 -2
- package/docs/vi/quality-gates.md +1 -1
- package/docs/vi/release-notes.md +1 -1
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/templates/_vendor/doc-export.js +292 -33
- package/tokens/element-seeds.json +1 -1
- package/tokens/native/CSTokens.kt +1 -1
- package/tokens/native/CSTokens.swift +1 -1
- package/tokens/native/cs_tokens.dart +1 -1
- package/tokens/provenance.json +6 -6
- package/tokens/tokens.dtcg.json +1 -1
- package/tokens/tokens.js +2 -2
- package/tokens/tokens.json +1 -1
package/DESIGN.md
CHANGED
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Start here
|
|
8
8
|
|
|
9
|
-
This is the **entrance document** for the CyberSkill Design System — VERSION **1.7.
|
|
9
|
+
This is the **entrance document** for the CyberSkill Design System — VERSION **1.7.2** (see `VERSION`). The **product site** is Storybook at **`/`** on `design.cyberskill.world` (host-only; local: `npm run storybook`). Operator documentation is published in the Storybook **Docs** sidebar (and the Documentation Library at `/docs/viewer.html`). Legacy `/dashboard`, `/dashboard.html`, and `/playground/*` redirect to `/`. One sentence: a warm, Vietnamese-first, enterprise-grade system where every surface resolves four independent axes — **Theme** (light · dark · system) × **Element** (Ngũ Hành product identity: Kim · Mộc · Thủy · Hỏa · Thổ, 15 variants) × **Language** (EN · VI) × **Style** (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default).
|
|
10
10
|
|
|
11
11
|
**Quick start by audience**
|
|
12
12
|
- **Designers** — open Storybook (**Foundations / Components / Templates / Pages / Docs**). **Templates** lists all 85 starting points (Gallery → Atomic View, plus category stories including the 38-document VN A4 suite (Employment Suite + commercial framework) under **Templates → HR**). Flip Theme × Element × Language × Style live via the Storybook toolbar, Atomic View, and the Elements Geometry specimen.
|
|
@@ -15,7 +15,7 @@ This is the **entrance document** for the CyberSkill Design System — VERSION *
|
|
|
15
15
|
|
|
16
16
|
- **Static / open-spec** (e.g. Google Stitch) — start at **`DESIGN.md`** (generated open-spec) → `llms.txt` → `tokens/tokens.dtcg.json`. Build **static** UI with `styles.css` + `.cs-*` / kitchen-sink / `examples/static-hello/`. **Do not** treat `templates/**/*.dc.html` as source of truth.
|
|
17
17
|
|
|
18
|
-
- **Implementers** — npm package **`@cyberskill/design@1.7.
|
|
18
|
+
- **Implementers** — npm package **`@cyberskill/design@1.7.2`** (see `docs/consuming.md`; grant in `docs/consumer-grant.md` — still UNLICENSED). **Next/SSR:** `import { Button } from "@cyberskill/design"` (peer React). **Browser demo:** **`examples/npm-hello/`** (Lumi · Hỏa · plasma, legacy `_esm/cs.mjs`). Or link **`styles.css`** from a clone/subtree (one file = everything), or copy a `templates/<slug>/` folder and edit one line in its `ds-base.js` (one-line rebind, validated end-to-end Jul 2026). Scope identity with `data-theme` · `data-cs-element` (+`data-cs-variant`) · `lang`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.2**; no CHANGELOG).
|
|
19
19
|
|
|
20
20
|
- **Maintainers** — `docs/doctrine.md` (expansion + verification), then `CONTRIBUTING.md` and `docs/quality-gates.md`.
|
|
21
21
|
|
|
@@ -170,7 +170,7 @@ Copied assets live in `assets/`: `logo-mark.svg` / `logo-mark.png` (official mas
|
|
|
170
170
|
|
|
171
171
|
Highlights: **Button** — Umber primary; variants primary/secondary/tertiary/ghost/danger/danger-ghost; sizes xs–lg; loading, icon, fullWidth. **TextField / Textarea / Select / NativeSelect** share one `.cs-field` frame (label + description/error; diacritic/IME-safe). **DataTable** — caption, scoped headers, per-column render, idle/loading/error/empty triad. **Card** — warm panel + header/body/footer. **Logo** renders the exact official mark; **Icon** drives the in-repo line-icon set. The **AI-native** family carries the brand's explainability doctrine — disclosure, human review, wish capture, and confidence, all stated in words (never colour alone).
|
|
172
172
|
|
|
173
|
-
**Install / package name.** This monolith publishes as **`@cyberskill/design`** (live at **1.7.
|
|
173
|
+
**Install / package name.** This monolith publishes as **`@cyberskill/design`** (live at **1.7.2**; grant in `docs/consumer-grant.md` governs *use* — package remains UNLICENSED). Do **not** install `@cyberskill/react` for this tree — that name is historical marketing-site inventory, not this package.
|
|
174
174
|
|
|
175
175
|
**Source inventory vs. extensions.** An earlier CyberSkill surface shipped six primitives — `Button`, `TextField`, `Dialog`, `DataTable`, `AIDisclosureBadge`, `HumanReviewGate` — plus a brand `Logo`. Everything else in **this** package is an **intentional extension** built in the brand's own token vocabulary so consumers have a complete working kit: `Icon` (the marketing site's real in-repo line-icon set), the standard Forms / Feedback / Data / Navigation / Overlays primitives (search, stepper, slider, file upload, list, description list, timeline, accordion, kbd, code block, sidebar, steps, command palette, popover, drawer, and more), added AI-native pieces (`PromptInput`, `ChatMessage`, `ConfidenceMeter`, `PromptSuggestions`, `TypingIndicator`, `CitationList`) that formalise the Lumi wish-flow, and the `LumiAvatar` mascot. None invent new visual language — they reuse the anchors, surfaces, type, and motion already defined.
|
|
176
176
|
|
|
@@ -283,7 +283,7 @@ Every template resolves to one of six archetypes, framed by `templates/doc-templ
|
|
|
283
283
|
## Index / manifest
|
|
284
284
|
|
|
285
285
|
```
|
|
286
|
-
styles.css ← single entry point (@import manifest only) · VERSION 1.7.
|
|
286
|
+
styles.css ← single entry point (@import manifest only) · VERSION 1.7.2
|
|
287
287
|
tokens/ fonts · colors · typography · spacing · elevation · motion · component-tokens · elements (Ngũ Hành packs)
|
|
288
288
|
base/ reset · typography · components · forms · feedback · data · navigation · ai · controls · collections · shell · glass · interaction · a11y · responsive
|
|
289
289
|
components/ button · textfield · dialog · datatable · forms · feedback · data · navigation · overlays · ai · logo · icon · brand
|
package/SKILL.md
CHANGED
|
@@ -17,7 +17,7 @@ If the user invokes this skill without any other guidance, ask them what they wa
|
|
|
17
17
|
| **Bundler React (Next/Vite/SSR)** | `docs/consuming.md` | `import { Button } from "@cyberskill/design"` + `styles.css`. React is a peer. |
|
|
18
18
|
| **Maintainers** | `docs/doctrine.md` | Expansion + verification; Storybook Docs at `design.cyberskill.world`. |
|
|
19
19
|
|
|
20
|
-
Dual-path detail: `docs/consuming.md`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.
|
|
20
|
+
Dual-path detail: `docs/consuming.md`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.2**; no CHANGELOG).
|
|
21
21
|
|
|
22
22
|
- **`README.md`** — the entrance + design guide + manifest: anchor immutables, CONTENT FUNDAMENTALS (voice = warm/direct/honest/respectful, Vietnamese-first, the "wish" metaphor), VISUAL FOUNDATIONS, ICONOGRAPHY, and the component/kit index. Read it first.
|
|
23
23
|
|
|
@@ -43,7 +43,7 @@ Dual-path detail: `docs/consuming.md`. Release signal: tip SHA + `docs/release-n
|
|
|
43
43
|
|
|
44
44
|
## Exporting
|
|
45
45
|
|
|
46
|
-
Every artifact exports, all paths preserving Vietnamese Unicode (see `docs/conventions.md` → Export paths). Decks → **editable PPTX** (`gen_pptx`, force VN per slide via `__dcSetProps`); documents (any with `@page{size}` / `omelette-owns-print`) → **PDF + editable DOCX** from one **Tải / Download** menu (`templates/_vendor/doc-export.js`, live `.cs-sheet`, no CDN; CI PDF via Playwright); emails / product pages / any DC → **standalone offline HTML** (make a same-folder `*-standalone.html` copy with static `<link>`/`<script>` resource tags, then `super_inline_html`). Contribution/expansion process is **`docs/doctrine.md`** + the decision log in `docs/conventions.md`; deep-verification harnesses live in `_audit/` (see `_audit/README.md`).
|
|
46
|
+
Every artifact exports, all paths preserving Vietnamese Unicode (see `docs/conventions.md` → Export paths). Decks → **editable PPTX** (`gen_pptx`, force VN per slide via `__dcSetProps`); documents (any with `@page{size}` / `omelette-owns-print`) → **PDF + editable DOCX** from one **Tải / Download** menu (`templates/_vendor/doc-export.js`, live `.cs-sheet`, Flate PDF + OOXML walk, no CDN; CI PDF via Playwright); emails / product pages / any DC → **standalone offline HTML** (make a same-folder `*-standalone.html` copy with static `<link>`/`<script>` resource tags, then `super_inline_html`). Contribution/expansion process is **`docs/doctrine.md`** + the decision log in `docs/conventions.md`; deep-verification harnesses live in `_audit/` (see `_audit/README.md`).
|
|
47
47
|
|
|
48
48
|
## Hard rules
|
|
49
49
|
|
|
@@ -63,7 +63,7 @@ Every artifact exports, all paths preserving Vietnamese Unicode (see `docs/conve
|
|
|
63
63
|
|
|
64
64
|
- Voice stays warm/direct/honest/respectful — never fun/playful/edgy. Products are "wishes" that Lumi helps grant.
|
|
65
65
|
|
|
66
|
-
- Expansion rule: when any set grows (element/variant, icon, component, language), update every deliverable in the same change — tokens, cards + related guidelines, contract trio, all template enums, Storybook toolbar / Atomic View, docs incl. every related document/README — and grep the old list to prove it. Full text: `docs/doctrine.md`. VERSION **1.7.
|
|
66
|
+
- Expansion rule: when any set grows (element/variant, icon, component, language), update every deliverable in the same change — tokens, cards + related guidelines, contract trio, all template enums, Storybook toolbar / Atomic View, docs incl. every related document/README — and grep the old list to prove it. Full text: `docs/doctrine.md`. VERSION **1.7.2** (auto-bumps on `main`; owner may still force a bump; no changelog).
|
|
67
67
|
|
|
68
68
|
- **Stitch / non-DC tools must not consume `*.dc.html` as source of truth.** Those files need the Design Components compiler (tweaks, `x-import`, `__dcSetProps`). Generate static UI from `DESIGN.md` / DTCG / `styles.css` + `.cs-*` / kitchen-sink / `examples/static-hello/` instead. DC authoring requires a compiler session (Claude Design, or a full clone with the compiler).
|
|
69
69
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.7.
|
|
1
|
+
1.7.2
|
package/_ds_bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"OverlayProvider","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"c8fc9f74a4c0","components/_i18n/strings.js":"0e63dc7515d8","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"344e9c13fcfe","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"68cf2bba3a9e","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"0ea06cfe1532","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"ed7615a9469a","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"9d419686bea8","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"3f30c6b1bf1d","components/data/Tree.jsx":"a1d33dec0451","components/data/Watermark.jsx":"66b7b71488d8","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"c84fe5d5b8cc","components/datatable/DataTable.jsx":"2a7c3bda5142","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"8ef7722c37c4","components/feedback/Alert.jsx":"4dbf685af3e1","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"5ba1437e6d81","components/feedback/ProgressBar.jsx":"c63a431e9eed","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"6a7832751669","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"63f35db7101d","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"194484fb9dc4","components/forms/FileUpload.jsx":"509dfaff8bea","components/forms/Form.jsx":"6945025a205f","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"3924619137f3","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"bd5c94741d63","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"009495d18845","components/forms/Slider.jsx":"213b7b9edec9","components/forms/Switch.jsx":"3cdf185f757c","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"abd6e54b2983","components/forms/Toggle.jsx":"a5378fd66713","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"280fba8477db","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"51c25b8416eb","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"999e1659f8b3","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"e26c4a18cdfc","components/navigation/Tabs.jsx":"16964d61f349","components/navigation/Toolbar.jsx":"0f1f25d9e0c5","components/overlays/AlertDialog.jsx":"dcfbb7f61506","components/overlays/ContextMenu.jsx":"e3fb63e7b74f","components/overlays/Drawer.jsx":"a1c719da3f62","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/OverlayManager.jsx":"6b58c4dad9da","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"707cd7464f0c","components/textfield/TextField.jsx":"c06bd9729f20","tokens/tokens.js":"c2ea96348d98"},"inlinedExternals":[],"unexposedExports":[{"name":"attachFocusTrap","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"focusableSelector","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getOverlayManager","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"reorderItems","sourcePath":"components/data/Sortable.jsx"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"},{"name":"useOverlayLayer","sourcePath":"components/overlays/OverlayManager.jsx"}]} */
|
|
1
|
+
/* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"OverlayProvider","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"c8fc9f74a4c0","components/_i18n/strings.js":"0e63dc7515d8","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"344e9c13fcfe","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"68cf2bba3a9e","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"0ea06cfe1532","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"ed7615a9469a","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"9d419686bea8","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"3f30c6b1bf1d","components/data/Tree.jsx":"a1d33dec0451","components/data/Watermark.jsx":"66b7b71488d8","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"c84fe5d5b8cc","components/datatable/DataTable.jsx":"2a7c3bda5142","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"8ef7722c37c4","components/feedback/Alert.jsx":"4dbf685af3e1","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"5ba1437e6d81","components/feedback/ProgressBar.jsx":"c63a431e9eed","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"6a7832751669","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"63f35db7101d","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"194484fb9dc4","components/forms/FileUpload.jsx":"509dfaff8bea","components/forms/Form.jsx":"6945025a205f","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"3924619137f3","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"bd5c94741d63","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"009495d18845","components/forms/Slider.jsx":"213b7b9edec9","components/forms/Switch.jsx":"3cdf185f757c","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"abd6e54b2983","components/forms/Toggle.jsx":"a5378fd66713","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"280fba8477db","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"51c25b8416eb","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"999e1659f8b3","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"e26c4a18cdfc","components/navigation/Tabs.jsx":"16964d61f349","components/navigation/Toolbar.jsx":"0f1f25d9e0c5","components/overlays/AlertDialog.jsx":"dcfbb7f61506","components/overlays/ContextMenu.jsx":"e3fb63e7b74f","components/overlays/Drawer.jsx":"a1c719da3f62","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/OverlayManager.jsx":"6b58c4dad9da","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"707cd7464f0c","components/textfield/TextField.jsx":"c06bd9729f20","tokens/tokens.js":"c4638b1eba09"},"inlinedExternals":[],"unexposedExports":[{"name":"attachFocusTrap","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"focusableSelector","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getOverlayManager","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"reorderItems","sourcePath":"components/data/Sortable.jsx"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"},{"name":"useOverlayLayer","sourcePath":"components/overlays/OverlayManager.jsx"}]} */
|
|
2
2
|
|
|
3
3
|
(() => {
|
|
4
4
|
|
|
@@ -4874,7 +4874,7 @@ try { (() => {
|
|
|
4874
4874
|
const tokens = {
|
|
4875
4875
|
"$meta": {
|
|
4876
4876
|
"system": "CyberSkill Design System",
|
|
4877
|
-
"version": "1.7.
|
|
4877
|
+
"version": "1.7.2",
|
|
4878
4878
|
"generated": "2026-07-23",
|
|
4879
4879
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
4880
4880
|
},
|
package/_esm/cs.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CyberSkill Design System — ESM entry point (GENERATED from _ds_manifest.json at v1.7.
|
|
1
|
+
// CyberSkill Design System — ESM entry point (GENERATED from _ds_manifest.json at v1.7.2).
|
|
2
2
|
// No build step: import this module directly in a browser. It ensures React 19.2.8 via umd-react
|
|
3
3
|
// (official React 19 dropped UMD; pinned + SRI; skipped when window.React already exists), side-loads
|
|
4
4
|
// ../_ds_bundle.js once, resolves the compiler-assigned namespace BY PREFIX (never a hardcoded suffix),
|
|
@@ -32,7 +32,7 @@ if (!found()) await ensureScript("../_ds_bundle.js");
|
|
|
32
32
|
export const CS = g[found()];
|
|
33
33
|
if (!CS) throw new Error("cs.js: bundle loaded but no CyberSkillDesignSystem_* namespace found");
|
|
34
34
|
export default CS;
|
|
35
|
-
export const VERSION = "1.7.
|
|
35
|
+
export const VERSION = "1.7.2";
|
|
36
36
|
export const AIDisclosureBadge = CS.AIDisclosureBadge;
|
|
37
37
|
export const Accordion = CS.Accordion;
|
|
38
38
|
export const Alert = CS.Alert;
|
package/docs/contrast-report.md
CHANGED
package/docs/conventions.md
CHANGED
|
@@ -38,7 +38,7 @@ Style’s sole pack today is **liquid-glass**. Immutable under all axes: Umber/O
|
|
|
38
38
|
|
|
39
39
|
**New element variant** — stay inside the element's oklch envelope; set the 10 `--cs-accent-*` contract tokens (incl. `--cs-accent-on-strong` ≥4.5:1 on `-strong`) plus `--cs-color-text-accent`/`--cs-color-link` (APCA-check both); the aurora wash inherits from the element via `.cs-aurora-wash` (override the class rule only if the variant truly needs its own image); gradient partner (`grad-b`) must follow Tương sinh.
|
|
40
40
|
|
|
41
|
-
**Ship check** — run the compiler check until clean, then run `_audit/docs-consistency.html` **and** `_audit/namespace-portability.html` (both must be green). VERSION **1.7.
|
|
41
|
+
**Ship check** — run the compiler check until clean, then run `_audit/docs-consistency.html` **and** `_audit/namespace-portability.html` (both must be green). VERSION **1.7.2** (auto-bumps on `main`).
|
|
42
42
|
|
|
43
43
|
## Decision log (owner-approved)
|
|
44
44
|
|
|
@@ -64,7 +64,7 @@ Every template exports; the right path depends on the archetype. All paths prese
|
|
|
64
64
|
| Archetype | Path | Notes |
|
|
65
65
|
|---|---|---|
|
|
66
66
|
| Deck (`*-deck`, `slide-deck`) | **PPTX (editable)** | `gen_pptx` at 960×540; force VN per-slide with `showJs: __dcSetProps(__dcRootName(),{language:'Tiếng Việt'})`. Text exports as native runs; only the Logo is an image. |
|
|
67
|
-
| Document (any with `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + editable DOCX** | One **Tải / Download** control (`data-omelette-chrome`, print-stripped) from `templates/_vendor/doc-export.js` via `ds-base.js`, with a PDF \| DOCX menu. Both formats are built from the live `.cs-sheet` so the file matches the HTML preview. **PDF** = one
|
|
67
|
+
| Document (any with `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + editable DOCX** | One **Tải / Download** control (`data-omelette-chrome`, print-stripped) from `templates/_vendor/doc-export.js` via `ds-base.js`, with a PDF \| DOCX menu. Both formats are built from the live `.cs-sheet` so the file matches the HTML preview. **PDF** = one Flate DeviceRGB page of the painted sheet at scale 3 (MediaBox aspect = the card — do not JPEG-blur, slice to A4, or stretch leftover slices); fallback: print a same-origin sheet clone — not the Storybook URL. CI still uses Playwright `page.pdf` for the print path. **DOCX** = editable OOXML walked from that same sheet (header flex as logo\|number table, measured font sizes/colors, tables + colspan, yellow `--cs-doc-fill` blanks, bilingual cell paras, umber headings, VN Unicode; Word header/footer stay empty so the sheet lockup is not duplicated); ZIP via `CompressionStream` — no CDN. Decks stay PPTX. |
|
|
68
68
|
| Email / product page / any DC | **Standalone offline HTML** | The DC loads CSS + bundle dynamically via `ds-base.js`, which `super_inline_html` can't see. To bundle: make a `*-standalone.html` copy **in the same folder** (keeps `./support.js` relative) with **static** `<link rel="stylesheet" href="../../styles.css">` + `<script src="../../_ds_bundle.js">` in the raw `<head>` (both inlinable) instead of `ds-base.js`, plus a `<template id="__bundler_thumbnail">`. Bake the target language into the props default. Then `super_inline_html`. |
|
|
69
69
|
| Any | **Editor-native + Claude Code handoff** | The whole project is dev-handoff-ready (compiled bundle + `.d.ts` + `prompt.md` per component); generate the package on request via the handoff skill. |
|
|
70
70
|
|
package/docs/quality-gates.md
CHANGED
|
@@ -52,7 +52,7 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
|
|
|
52
52
|
| Axe smoke | `_audit/axe-smoke.html` + `_audit/lib/axe-fixtures.js` | axe-core 4.10.0 (vendored at `_audit/vendor/axe.min.js`) serious/critical WCAG 2 A/AA rules on every public primary (inventory-locked fixtures; bilingual EN·VI) — Dialog, AlertDialog, Drawer, Tour, CommandPalette, and Menu mount open, and Cascader / TreeSelect / Menubar / Combobox surfaces are expanded before the scan; gate-equivalent Storybook a11y enforcement (no separate test-runner) | 0 serious/critical findings (`__axesmoke`) | Hard | Fast board CI |
|
|
53
53
|
| Print smoke | `_audit/print-smoke.html` | **Every** `omelette-owns-print` document declares print-ownership meta and A4/Letter `@page` hooks the PDF/DOCX export path relies on | ≥60 print docs, 0 missing hooks (`__printsmoke`) | Hard | Fast board CI |
|
|
54
54
|
| Support no-eval (Node) | `_audit/ci/test-support-no-eval.mjs` | Canonical `templates/_vendor/support.js` + all template copies are identical and contain no Function-constructor / `eval(` call sites (CSP-safe inline-script runtime) | Exit 0 | Hard | Unit test |
|
|
55
|
-
| Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Every print template under site CSP: no EvalError, one Download menu (PDF\|DOCX), Playwright PDF `%PDF` + A4/Letter MediaBox, downloaded `buildPdfBlob` is one unstretched page of the live sheet (framework), DOCX ZIP + `word/document.xml` + VN diacritics + ≥70% sheet-text overlap + yellow fills/colspan on framework | Exit 0 | Hard | Unit test |
|
|
55
|
+
| Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Every print template under site CSP: no EvalError, one Download menu (PDF\|DOCX), Playwright PDF `%PDF` + A4/Letter MediaBox, downloaded `buildPdfBlob` is one unstretched FlateDecode page of the live sheet (framework), DOCX ZIP + `word/document.xml` + VN diacritics + ≥70% sheet-text overlap + yellow fills/colspan + header lockup text (HĐNT) on framework | Exit 0 | Hard | Unit test |
|
|
56
56
|
| DOCX source parity (Node) | `_audit/ci/test-docx-source-parity.mjs` | DC text vs committed fixtures under `_audit/fixtures/hr-suite-docx-text/` for every mapped HR instrument | ≥85% phrase overlap; exit 0 | Hard | Unit test |
|
|
57
57
|
| Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` | 15 curated baselines exist; Playwright capture script performs real % pixel compare; last report must be clean (`drifted[]` empty) | Contract + clean compare (`__pixelci.pass`); drift or missing report fails | Hard | Fast board CI (compare step feeds the row) + `pixel-diff` job |
|
|
58
58
|
|
package/docs/release-notes.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
-
Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. VERSION **1.7.
|
|
3
|
+
Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. VERSION **1.7.2** (auto-bumps on push to `main` from Conventional Commits; owner may still force a bump). Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**). Published on Storybook **Docs** at `design.cyberskill.world`.
|
|
4
4
|
|
|
5
5
|
## Release — `@cyberskill/design@1.3.10`
|
|
6
6
|
|
package/docs/vi/conventions.md
CHANGED
|
@@ -38,7 +38,7 @@ Pack Style duy nhất hiện nay là **liquid-glass**. Bất biến dưới mọ
|
|
|
38
38
|
|
|
39
39
|
**Element variant mới** — ở trong envelope oklch của element; đặt 10 token hợp đồng `--cs-accent-*` (gồm `--cs-accent-on-strong` ≥4.5:1 trên `-strong`) cộng `--cs-color-text-accent`/`--cs-color-link` (APCA-check cả hai); aurora wash kế thừa từ element qua `.cs-aurora-wash` (chỉ override class rule nếu variant thật sự cần ảnh riêng); đối tác gradient (`grad-b`) phải theo Tương sinh.
|
|
40
40
|
|
|
41
|
-
**Ship check** — chạy compiler check đến sạch, rồi chạy `_audit/docs-consistency.html` **và** `_audit/namespace-portability.html` (cả hai phải xanh). VERSION **1.7.
|
|
41
|
+
**Ship check** — chạy compiler check đến sạch, rồi chạy `_audit/docs-consistency.html` **và** `_audit/namespace-portability.html` (cả hai phải xanh). VERSION **1.7.2** (auto-bump trên `main`).
|
|
42
42
|
|
|
43
43
|
## Decision log (owner duyệt)
|
|
44
44
|
|
|
@@ -64,7 +64,7 @@ Mọi template export; đường đúng phụ thuộc archetype. Mọi đường
|
|
|
64
64
|
| Archetype | Đường | Ghi chú |
|
|
65
65
|
|---|---|---|
|
|
66
66
|
| Deck (`*-deck`, `slide-deck`) | **PPTX (editable)** | `gen_pptx` ở 960×540; ép VN từng slide với `showJs: __dcSetProps(__dcRootName(),{language:'Tiếng Việt'})`. Text export như native runs; chỉ Logo là ảnh. |
|
|
67
|
-
| Document (mọi cái có `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + DOCX chỉnh sửa được** | Một nút **Tải / Download** (`data-omelette-chrome`, ẩn khi in) từ `templates/_vendor/doc-export.js` qua `ds-base.js`, menu PDF \| DOCX. Cả hai format dựng từ `.cs-sheet` sống để file khớp preview HTML. **PDF** = một trang
|
|
67
|
+
| Document (mọi cái có `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + DOCX chỉnh sửa được** | Một nút **Tải / Download** (`data-omelette-chrome`, ẩn khi in) từ `templates/_vendor/doc-export.js` qua `ds-base.js`, menu PDF \| DOCX. Cả hai format dựng từ `.cs-sheet` sống để file khớp preview HTML. **PDF** = một trang Flate DeviceRGB của sheet đã vẽ, scale 3 (tỉ lệ MediaBox = thẻ — không JPEG mờ, không cắt A4 hay kéo dãn lát cuối); fallback: in bản clone same-origin — không phải URL Storybook. CI vẫn dùng Playwright `page.pdf` cho đường in. **DOCX** = OOXML editable walk từ cùng sheet (flex header thành bảng logo\|số, cỡ/màu chữ đo được, bảng + colspan, ô vàng `--cs-doc-fill`, đoạn bilingual trong ô, heading umber, Unicode VN; header/footer Word để trống để không nhân đôi lockup); ZIP qua `CompressionStream` — không CDN. Deck vẫn PPTX. |
|
|
68
68
|
| Email / product page / mọi DC | **Standalone offline HTML** | DC load CSS + bundle động qua `ds-base.js`, mà `super_inline_html` không thấy. Để bundle: tạo bản `*-standalone.html` **cùng thư mục** (giữ `./support.js` relative) với `<link rel="stylesheet" href="../../styles.css">` + `<script src="../../_ds_bundle.js">` **static** trong raw `<head>` (cả hai inline được) thay `ds-base.js`, cộng `<template id="__bundler_thumbnail">`. Nướng ngôn ngữ đích vào props default. Rồi `super_inline_html`. |
|
|
69
69
|
| Bất kỳ | **Editor-native + Claude Code handoff** | Cả project sẵn sàng handoff-dev (compiled bundle + `.d.ts` + `prompt.md` mỗi component); generate package theo request qua handoff skill. |
|
|
70
70
|
|
package/docs/vi/quality-gates.md
CHANGED
|
@@ -52,7 +52,7 @@ Nguyên tắc benchmark (WCAG · APCA · OKLCH · DTCG · doctrine CDS + mở r
|
|
|
52
52
|
| Axe smoke | `_audit/axe-smoke.html` + `_audit/lib/axe-fixtures.js` | Rule serious/critical WCAG 2 A/AA của axe-core 4.10.0 (vendored tại `_audit/vendor/axe.min.js`) trên mọi public primary (fixture khoá inventory; bilingual EN·VI) — Dialog, AlertDialog, Drawer, Tour, CommandPalette và Menu mount mở, còn Cascader / TreeSelect / Menubar / Combobox được bung trước khi quét; tương đương enforcement a11y Storybook (không test-runner riêng) | 0 finding serious/critical (`__axesmoke`) | Hard | Fast board CI |
|
|
53
53
|
| Print smoke | `_audit/print-smoke.html` | **Every** `omelette-owns-print` document declares print-ownership meta and A4/Letter `@page` hooks the PDF/DOCX export path relies on | ≥60 print docs, 0 missing hooks (`__printsmoke`) | Hard | Fast board CI |
|
|
54
54
|
| Support no-eval (Node) | `_audit/ci/test-support-no-eval.mjs` | Canonical `templates/_vendor/support.js` + all template copies are identical and contain no Function-constructor / `eval(` call sites (CSP-safe inline-script runtime) | Exit 0 | Hard | Unit test |
|
|
55
|
-
| Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Mọi template in dưới CSP site: không EvalError, một menu Download (PDF\|DOCX), PDF Playwright `%PDF` + MediaBox A4/Letter, `buildPdfBlob` tải về là một trang không méo của sheet sống (framework), DOCX ZIP + `word/document.xml` + dấu VN + ≥70% chồng text sheet + fill vàng/colspan trên framework | Exit 0 | Hard | Unit test |
|
|
55
|
+
| Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Mọi template in dưới CSP site: không EvalError, một menu Download (PDF\|DOCX), PDF Playwright `%PDF` + MediaBox A4/Letter, `buildPdfBlob` tải về là một trang FlateDecode không méo của sheet sống (framework), DOCX ZIP + `word/document.xml` + dấu VN + ≥70% chồng text sheet + fill vàng/colspan + text lockup header (HĐNT) trên framework | Exit 0 | Hard | Unit test |
|
|
56
56
|
| DOCX source parity (Node) | `_audit/ci/test-docx-source-parity.mjs` | DC text vs committed fixtures under `_audit/fixtures/hr-suite-docx-text/` for every mapped HR instrument | ≥85% phrase overlap; exit 0 | Hard | Unit test |
|
|
57
57
|
| Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` | 15 baseline curated tồn tại; script Playwright capture so sánh % pixel thật; report gần nhất phải sạch (`drifted[]` rỗng) | Hợp đồng + compare sạch (`__pixelci.pass`); drift hoặc thiếu report → fail | Hard | Fast board CI (bước compare nuôi hàng) + job `pixel-diff` |
|
|
58
58
|
|
package/docs/vi/release-notes.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ghi chú phát hành
|
|
2
2
|
|
|
3
|
-
Điểm nổi bật sản phẩm cho operator — **không** phải git log và **không** phải `CHANGELOG.md`. Hệ thống thiết kế không maintain file changelog. VERSION **1.7.
|
|
3
|
+
Điểm nổi bật sản phẩm cho operator — **không** phải git log và **không** phải `CHANGELOG.md`. Hệ thống thiết kế không maintain file changelog. VERSION **1.7.2** (auto-bump khi push lên `main` từ Conventional Commits; owner vẫn có thể force bump). Chân lý kỹ thuật là tip repo; chân lý hướng sản phẩm là trang này (đồng bộ Storybook **Release Notes**). Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
|
|
4
4
|
|
|
5
5
|
## Release — `@cyberskill/design@1.3.10`
|
|
6
6
|
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CyberSkill Design System
|
|
2
2
|
|
|
3
|
-
> HTML-first, Vietnamese-first design system, VERSION **1.7.
|
|
3
|
+
> HTML-first, Vietnamese-first design system, VERSION **1.7.2**. Immutable anchors: Umber #45210E · Ochre #F4BA17. Four independent axes — Theme (light · dark · system) × Element (Ngũ Hành, 15 variants) × Language (EN · VI) × Style (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default). It ships 106 components / 122 exports, 85 copyable templates (EN·VN for emails + team/legal/finance; client/media collateral EN-first), and tokens in CSS + JSON + ESM + W3C DTCG + native mirrors. This file is the agent/tool front door: it maps each **capability** to the format it should consume. npm package name is **`@cyberskill/design`** (not `@cyberskill/react`). Release signal: tip SHA + [docs/release-notes.md](docs/release-notes.md) — VERSION **1.7.2**, no CHANGELOG.
|
|
4
4
|
|
|
5
5
|
The portable contract covers browser and bundler entry points: `styles.css` · `_esm/cs.mjs` legacy · `_ds_bundle.js` · tokens work without a build step; `_esm/react.mjs` is bundler-native JSX (Next/Vite must transpile — not a bare-browser import). The DC layer (`templates/**/*.dc.html`) needs a **Design Components compiler**. **Google Stitch must not treat `*.dc.html` as source of truth** — use `DESIGN.md`, DTCG, `styles.css`, kitchen-sink, and `.cs-*` static HTML instead. Dual path: [docs/consuming.md](docs/consuming.md). The full non-negotiables list lives in `CONTRIBUTING.md` and `docs/doctrine.md`. Operator docs are published on the Storybook **Docs** sidebar at `design.cyberskill.world`.
|
|
6
6
|
|
|
@@ -31,7 +31,7 @@ The portable contract covers browser and bundler entry points: `styles.css` · `
|
|
|
31
31
|
- [templates/](templates/): 85 copyable starting points (`.dc.html`); `email-safe/` send-ready emails; `kitchen-sink.html`; `playground.html`
|
|
32
32
|
- [guidelines/](guidelines/): specimen cards + `atomic-view.html` (portable component grid) — host product surface is Storybook at `/`
|
|
33
33
|
- [examples/static-hello/](examples/static-hello/): zero-install static consumer (Stitch / plain HTML)
|
|
34
|
-
- [examples/npm-hello/](examples/npm-hello/): first registry **browser** consumer — `@cyberskill/design@1.7.
|
|
34
|
+
- [examples/npm-hello/](examples/npm-hello/): first registry **browser** consumer — `@cyberskill/design@1.7.2` legacy entry (Lumi · Hỏa · plasma); Status Hub teams swap to `thuy`; Next/SSR apps use default `@cyberskill/design` React entry instead
|
|
35
35
|
- [examples/native/](examples/native/): SwiftUI / Compose / Flutter sample apps + store scaffolds — Compose is **Android Studio**-first (no committed `gradlew`; see `examples/native/README.md`)
|
|
36
36
|
- [ui_kits/](ui_kits/): product recreations — status-hub · website · deck
|
|
37
37
|
- [fonts/](fonts/): self-hosted Be Vietnam Pro (UI) + Space Grotesk (opt-in display, `--cs-font-family-display`) + JetBrains Mono woff2
|
|
@@ -48,7 +48,7 @@ The portable contract covers browser and bundler entry points: `styles.css` · `
|
|
|
48
48
|
Published on Storybook **Docs** (`design.cyberskill.world`) and in [docs/viewer.html](docs/viewer.html) (EN|VI).
|
|
49
49
|
|
|
50
50
|
- [docs/consuming.md](docs/consuming.md): adopting & upgrading, DC-capable vs static dual path, package name `@cyberskill/design`; first registry install at [examples/npm-hello/](examples/npm-hello/) (Lumi · Hỏa · plasma); native mirrors at [examples/native/](examples/native/) (SwiftUI / Compose / Flutter samples)
|
|
51
|
-
- [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog) — includes `@cyberskill/design@1.7.
|
|
51
|
+
- [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog) — includes `@cyberskill/design@1.7.2` Trusted Publishing / grant pointer
|
|
52
52
|
- [docs/consumer-grant.md](docs/consumer-grant.md): written npm grant (CyberSkill portfolio; UNLICENSED)
|
|
53
53
|
- [docs/conventions.md](docs/conventions.md): authoring rules (naming grammar, the four axes)
|
|
54
54
|
- [docs/design-styles.md](docs/design-styles.md): the live styling axes and the fixed liquid-glass treatment
|
package/package.json
CHANGED
|
@@ -128,23 +128,40 @@
|
|
|
128
128
|
return bg && /rgb\(\s*253\s*,\s*230\s*,\s*138\s*\)/i.test(bg);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function rgbToHex(rgb) {
|
|
132
|
+
const m = rgb && String(rgb).match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
|
|
133
|
+
if (!m) return null;
|
|
134
|
+
const r = Number(m[1]);
|
|
135
|
+
const g = Number(m[2]);
|
|
136
|
+
const b = Number(m[3]);
|
|
137
|
+
if (r < 25 && g < 25 && b < 25) return null;
|
|
138
|
+
const hex = [r, g, b].map((n) => n.toString(16).padStart(2, '0')).join('').toUpperCase();
|
|
139
|
+
return hex === '000000' ? null : hex;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function halfPt(fontSize) {
|
|
143
|
+
const px = parseFloat(fontSize);
|
|
144
|
+
if (!px) return null;
|
|
145
|
+
return Math.max(14, Math.round((px * 72) / 96) * 2);
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
function textRuns(el) {
|
|
132
149
|
const parts = [];
|
|
133
|
-
const walk = (node, italic, bold, color, fill) => {
|
|
150
|
+
const walk = (node, italic, bold, color, fill, size) => {
|
|
134
151
|
if (node.nodeType === 3) {
|
|
135
152
|
const raw = node.textContent || '';
|
|
136
153
|
if (!raw) return;
|
|
137
154
|
if (!raw.replace(/\s+/g, '').length) {
|
|
138
|
-
if (parts.length) parts.push({ t: ' ', italic, bold, color, fill });
|
|
155
|
+
if (parts.length) parts.push({ t: ' ', italic, bold, color, fill, size });
|
|
139
156
|
return;
|
|
140
157
|
}
|
|
141
|
-
parts.push({ t: raw.replace(/\s+/g, ' '), italic, bold, color, fill });
|
|
158
|
+
parts.push({ t: raw.replace(/\s+/g, ' '), italic, bold, color, fill, size });
|
|
142
159
|
return;
|
|
143
160
|
}
|
|
144
161
|
if (node.nodeType !== 1) return;
|
|
145
162
|
if (isChrome(node)) return;
|
|
146
163
|
const tag = node.tagName.toLowerCase();
|
|
147
|
-
if (tag === 'script' || tag === 'style' || tag === 'noscript') return;
|
|
164
|
+
if (tag === 'script' || tag === 'style' || tag === 'noscript' || tag === 'svg') return;
|
|
148
165
|
const st = window.getComputedStyle(node);
|
|
149
166
|
const nextItalic = italic || st.fontStyle === 'italic' || tag === 'i' || tag === 'em';
|
|
150
167
|
const nextBold =
|
|
@@ -156,23 +173,33 @@
|
|
|
156
173
|
let nextColor = color;
|
|
157
174
|
if (/^h[1-6]$/.test(tag) || (st.color && /rgb\(\s*69\s*,\s*33\s*,\s*14\s*\)/.test(st.color))) {
|
|
158
175
|
nextColor = UMBER;
|
|
176
|
+
} else {
|
|
177
|
+
nextColor = rgbToHex(st.color) || color;
|
|
159
178
|
}
|
|
160
179
|
const nextFill = fill || (isDocFillColor(st.backgroundColor) ? DOC_FILL : null);
|
|
180
|
+
const nextSize = halfPt(st.fontSize) || size;
|
|
161
181
|
const kids = [...node.childNodes];
|
|
162
182
|
for (let i = 0; i < kids.length; i++) {
|
|
163
183
|
const before = parts.length;
|
|
164
|
-
walk(kids[i], nextItalic, nextBold, nextColor, nextFill);
|
|
184
|
+
walk(kids[i], nextItalic, nextBold, nextColor, nextFill, nextSize);
|
|
165
185
|
const nxt = kids[i + 1];
|
|
166
186
|
if (parts.length > before && nxt) {
|
|
167
187
|
const last = parts[parts.length - 1];
|
|
168
188
|
const nextRaw = nxt.textContent || '';
|
|
169
189
|
if (last && last.t && !/\s$/.test(last.t) && nextRaw.replace(/\s+/g, '') && !/^\s/.test(nextRaw)) {
|
|
170
|
-
parts.push({
|
|
190
|
+
parts.push({
|
|
191
|
+
t: ' ',
|
|
192
|
+
italic: nextItalic,
|
|
193
|
+
bold: nextBold,
|
|
194
|
+
color: nextColor,
|
|
195
|
+
fill: nextFill,
|
|
196
|
+
size: nextSize,
|
|
197
|
+
});
|
|
171
198
|
}
|
|
172
199
|
}
|
|
173
200
|
}
|
|
174
201
|
};
|
|
175
|
-
walk(el, false, false, null, null);
|
|
202
|
+
walk(el, false, false, null, null, null);
|
|
176
203
|
const merged = [];
|
|
177
204
|
for (const r of parts) {
|
|
178
205
|
const prev = merged[merged.length - 1];
|
|
@@ -181,7 +208,8 @@
|
|
|
181
208
|
prev.italic === r.italic &&
|
|
182
209
|
prev.bold === r.bold &&
|
|
183
210
|
prev.color === r.color &&
|
|
184
|
-
prev.fill === r.fill
|
|
211
|
+
prev.fill === r.fill &&
|
|
212
|
+
prev.size === r.size
|
|
185
213
|
) {
|
|
186
214
|
prev.t += r.t;
|
|
187
215
|
} else {
|
|
@@ -202,6 +230,7 @@
|
|
|
202
230
|
if (r.italic) rPr.push('<w:i/>');
|
|
203
231
|
if (r.color) rPr.push(`<w:color w:val="${r.color}"/>`);
|
|
204
232
|
if (r.fill) rPr.push(`<w:shd w:val="clear" w:fill="${r.fill}"/><w:highlight w:val="yellow"/>`);
|
|
233
|
+
if (r.size) rPr.push(`<w:sz w:val="${r.size}"/><w:szCs w:val="${r.size}"/>`);
|
|
205
234
|
rPr.push('<w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/>');
|
|
206
235
|
const pr = rPr.length ? `<w:rPr>${rPr.join('')}</w:rPr>` : '';
|
|
207
236
|
return `<w:r>${pr}<w:t xml:space="preserve">${xmlEscape(r.t)}</w:t></w:r>`;
|
|
@@ -213,9 +242,13 @@
|
|
|
213
242
|
const bits = [];
|
|
214
243
|
if (style) bits.push(`<w:pStyle w:val="${style}"/>`);
|
|
215
244
|
if (el) {
|
|
216
|
-
const
|
|
245
|
+
const st = window.getComputedStyle(el);
|
|
246
|
+
const ta = st.textAlign;
|
|
217
247
|
if (ta === 'center') bits.push('<w:jc w:val="center"/>');
|
|
218
248
|
else if (ta === 'right' || ta === 'end') bits.push('<w:jc w:val="right"/>');
|
|
249
|
+
const before = Math.max(0, Math.round((parseFloat(st.marginTop) || 0) * 15));
|
|
250
|
+
const after = Math.max(0, Math.round((parseFloat(st.marginBottom) || 0) * 15));
|
|
251
|
+
if (before || after) bits.push(`<w:spacing w:before="${before}" w:after="${after}"/>`);
|
|
219
252
|
}
|
|
220
253
|
return bits.length ? `<w:pPr>${bits.join('')}</w:pPr>` : '';
|
|
221
254
|
}
|
|
@@ -256,8 +289,20 @@
|
|
|
256
289
|
const rows = [...table.querySelectorAll(':scope > tbody > tr, :scope > thead > tr, :scope > tr')];
|
|
257
290
|
if (!rows.length) return '';
|
|
258
291
|
const gridCols = Math.max(...rows.map(rowColCount), 1);
|
|
259
|
-
|
|
260
|
-
|
|
292
|
+
let colWidths;
|
|
293
|
+
if (gridCols === 2) {
|
|
294
|
+
const tableW = table.getBoundingClientRect().width || 1;
|
|
295
|
+
const sample = rows.find((r) => r.children.length >= 2) || rows[0];
|
|
296
|
+
const c0 = sample && sample.children[0];
|
|
297
|
+
const ratio = c0 ? c0.getBoundingClientRect().width / tableW : 0.28;
|
|
298
|
+
const col0 = Math.round(9000 * Math.min(0.42, Math.max(0.18, ratio)));
|
|
299
|
+
colWidths = [col0, 9000 - col0];
|
|
300
|
+
} else {
|
|
301
|
+
const even = Math.floor(9000 / gridCols);
|
|
302
|
+
colWidths = Array.from({ length: gridCols }, () => even);
|
|
303
|
+
}
|
|
304
|
+
const gridColsXml = colWidths.map((w) => `<w:gridCol w:w="${w}"/>`).join('');
|
|
305
|
+
const colW = colWidths[0];
|
|
261
306
|
let xml = `<w:tbl><w:tblPr><w:tblW w:w="5000" w:type="pct"/><w:tblBorders>
|
|
262
307
|
<w:top w:val="single" w:sz="4" w:color="C9B8A8"/>
|
|
263
308
|
<w:left w:val="single" w:sz="4" w:color="C9B8A8"/>
|
|
@@ -279,7 +324,8 @@
|
|
|
279
324
|
: yellowFill
|
|
280
325
|
? `<w:shd w:val="clear" w:fill="${DOC_FILL}"/>`
|
|
281
326
|
: '';
|
|
282
|
-
|
|
327
|
+
const tw = colWidths.slice(0, span).reduce((n, w) => n + w, 0);
|
|
328
|
+
xml += `<w:tc><w:tcPr>${fillXml}${spanXml}<w:tcW w:w="${tw}" w:type="dxa"/></w:tcPr>${cellInnerXml(cell, umberFill)}</w:tc>`;
|
|
283
329
|
}
|
|
284
330
|
xml += '</w:tr>';
|
|
285
331
|
}
|
|
@@ -319,13 +365,162 @@
|
|
|
319
365
|
return xml;
|
|
320
366
|
}
|
|
321
367
|
|
|
322
|
-
function
|
|
368
|
+
function drawingRun(relId, cx, cy) {
|
|
369
|
+
return `<w:r><w:drawing>
|
|
370
|
+
<wp:inline distT="0" distB="0" distL="0" distR="0">
|
|
371
|
+
<wp:extent cx="${cx}" cy="${cy}"/>
|
|
372
|
+
<wp:docPr id="${relId.replace(/\D/g, '') || '1'}" name="img"/>
|
|
373
|
+
<a:graphic>
|
|
374
|
+
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
|
|
375
|
+
<pic:pic>
|
|
376
|
+
<pic:nvPicPr><pic:cNvPr id="0" name="image.png"/><pic:cNvPicPr/></pic:nvPicPr>
|
|
377
|
+
<pic:blipFill><a:blip r:embed="${relId}"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill>
|
|
378
|
+
<pic:spPr>
|
|
379
|
+
<a:xfrm><a:off x="0" y="0"/><a:ext cx="${cx}" cy="${cy}"/></a:xfrm>
|
|
380
|
+
<a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
|
|
381
|
+
</pic:spPr>
|
|
382
|
+
</pic:pic>
|
|
383
|
+
</a:graphicData>
|
|
384
|
+
</a:graphic>
|
|
385
|
+
</wp:inline>
|
|
386
|
+
</w:drawing></w:r>`;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function findSvg(el) {
|
|
390
|
+
if (!el || el.nodeType !== 1) return null;
|
|
391
|
+
if (el.tagName.toLowerCase() === 'svg') return el;
|
|
392
|
+
const light = el.querySelector?.('svg');
|
|
393
|
+
if (light) return light;
|
|
394
|
+
if (el.shadowRoot) {
|
|
395
|
+
const sh = el.shadowRoot.querySelector('svg');
|
|
396
|
+
if (sh) return sh;
|
|
397
|
+
}
|
|
398
|
+
for (const c of el.children || []) {
|
|
399
|
+
const nested = findSvg(c);
|
|
400
|
+
if (nested) return nested;
|
|
401
|
+
}
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
async function addSvgPng(svg, bag) {
|
|
406
|
+
const box = svg.getBoundingClientRect();
|
|
407
|
+
const cssW = Math.max(box.width || parseFloat(svg.getAttribute('width')) || 18, 12);
|
|
408
|
+
const cssH = Math.max(box.height || parseFloat(svg.getAttribute('height')) || cssW, 12);
|
|
409
|
+
const scale = 3;
|
|
410
|
+
const w = Math.max(1, Math.round(cssW * scale));
|
|
411
|
+
const h = Math.max(1, Math.round(cssH * scale));
|
|
412
|
+
try {
|
|
413
|
+
const clone = svg.cloneNode(true);
|
|
414
|
+
clone.setAttribute('width', String(cssW));
|
|
415
|
+
clone.setAttribute('height', String(cssH));
|
|
416
|
+
if (!clone.getAttribute('xmlns')) clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
417
|
+
const xml = new XMLSerializer().serializeToString(clone);
|
|
418
|
+
if (/foreignObject/i.test(xml)) return '';
|
|
419
|
+
const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });
|
|
420
|
+
const url = URL.createObjectURL(blob);
|
|
421
|
+
try {
|
|
422
|
+
const img = await loadImage(url);
|
|
423
|
+
const c = document.createElement('canvas');
|
|
424
|
+
c.width = w;
|
|
425
|
+
c.height = h;
|
|
426
|
+
const ctx = c.getContext('2d');
|
|
427
|
+
ctx.drawImage(img, 0, 0, w, h);
|
|
428
|
+
const bytes = dataUrlToBytes(c.toDataURL('image/png'));
|
|
429
|
+
const n = bag.media.length + 1;
|
|
430
|
+
const relId = `rIdImg${n}`;
|
|
431
|
+
bag.media.push({ name: `word/media/image${n}.png`, bytes, relId });
|
|
432
|
+
const emu = Math.round(cssW * 9525);
|
|
433
|
+
return drawingRun(relId, emu, Math.round(emu * (h / w)));
|
|
434
|
+
} finally {
|
|
435
|
+
URL.revokeObjectURL(url);
|
|
436
|
+
}
|
|
437
|
+
} catch (_) {
|
|
438
|
+
return '';
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async function groupInnerXml(els, bag) {
|
|
443
|
+
let drawings = '';
|
|
444
|
+
const textEls = [];
|
|
445
|
+
for (const el of els) {
|
|
446
|
+
const svg = findSvg(el);
|
|
447
|
+
if (svg) drawings += await addSvgPng(svg, bag);
|
|
448
|
+
if (!svg || textRuns(el).length) textEls.push(el);
|
|
449
|
+
}
|
|
450
|
+
let runs = [];
|
|
451
|
+
for (const el of textEls) {
|
|
452
|
+
const next = textRuns(el);
|
|
453
|
+
if (
|
|
454
|
+
runs.length &&
|
|
455
|
+
next.length &&
|
|
456
|
+
!/\s$/.test(runs[runs.length - 1].t) &&
|
|
457
|
+
!/^\s/.test(next[0].t)
|
|
458
|
+
) {
|
|
459
|
+
runs.push({
|
|
460
|
+
t: ' ',
|
|
461
|
+
italic: next[0].italic,
|
|
462
|
+
bold: next[0].bold,
|
|
463
|
+
color: next[0].color,
|
|
464
|
+
fill: next[0].fill,
|
|
465
|
+
size: next[0].size,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
runs.push(...next);
|
|
469
|
+
}
|
|
470
|
+
if (!drawings && !runs.length) return `<w:p>${runsToXml([])}</w:p>`;
|
|
471
|
+
return `<w:p>${pPrXml(textEls[0] || els[0])}${drawings}${runsToXml(runs)}</w:p>`;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async function flexAsTable(el, bag) {
|
|
475
|
+
const st = window.getComputedStyle(el);
|
|
476
|
+
if (st.display !== 'flex' && st.display !== 'inline-flex') return '';
|
|
477
|
+
const dir = st.flexDirection || 'row';
|
|
478
|
+
if (dir === 'column' || dir === 'column-reverse') return '';
|
|
479
|
+
const kids = [...el.children].filter((c) => c.nodeType === 1 && !isChrome(c));
|
|
480
|
+
if (kids.length < 2) return '';
|
|
481
|
+
const hasLogo = kids.some((c) => {
|
|
482
|
+
const t = c.tagName.toLowerCase();
|
|
483
|
+
return t === 'svg' || t === 'x-import' || !!findSvg(c);
|
|
484
|
+
});
|
|
485
|
+
if (!hasLogo && kids.length !== 2) return '';
|
|
486
|
+
let split = -1;
|
|
487
|
+
for (let i = 1; i < kids.length; i++) {
|
|
488
|
+
const inline = kids[i].style?.marginLeft || '';
|
|
489
|
+
const attr = kids[i].getAttribute?.('style') || '';
|
|
490
|
+
if (inline === 'auto' || /margin-left\s*:\s*auto/i.test(attr)) {
|
|
491
|
+
split = i;
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (split < 0) {
|
|
496
|
+
if (kids.length === 2) split = 1;
|
|
497
|
+
else return '';
|
|
498
|
+
}
|
|
499
|
+
const left = await groupInnerXml(kids.slice(0, split), bag);
|
|
500
|
+
const right = await groupInnerXml(kids.slice(split), bag);
|
|
501
|
+
return `<w:tbl><w:tblPr><w:tblW w:w="5000" w:type="pct"/><w:tblBorders>
|
|
502
|
+
<w:top w:val="nil"/><w:left w:val="nil"/><w:bottom w:val="nil"/><w:right w:val="nil"/>
|
|
503
|
+
<w:insideH w:val="nil"/><w:insideV w:val="nil"/>
|
|
504
|
+
</w:tblBorders></w:tblPr><w:tblGrid><w:gridCol w:w="6200"/><w:gridCol w:w="2800"/></w:tblGrid>
|
|
505
|
+
<w:tr>
|
|
506
|
+
<w:tc><w:tcPr><w:tcW w:w="6200" w:type="dxa"/></w:tcPr>${left}</w:tc>
|
|
507
|
+
<w:tc><w:tcPr><w:tcW w:w="2800" w:type="dxa"/></w:tcPr>${right}</w:tc>
|
|
508
|
+
</w:tr></w:tbl>`;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
async function sheetBodyXml(sheet, bag) {
|
|
323
512
|
const blocks = [];
|
|
324
|
-
const visit = (nodes) => {
|
|
513
|
+
const visit = async (nodes) => {
|
|
325
514
|
for (const el of nodes) {
|
|
326
515
|
if (el.nodeType !== 1) continue;
|
|
327
516
|
if (isChrome(el)) continue;
|
|
328
517
|
const tag = el.tagName.toLowerCase();
|
|
518
|
+
const svg = findSvg(el);
|
|
519
|
+
if (svg && (tag === 'svg' || !textRuns(el).length)) {
|
|
520
|
+
const drawing = await addSvgPng(svg, bag);
|
|
521
|
+
if (drawing) blocks.push(`<w:p>${drawing}</w:p>`);
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
329
524
|
if (tag === 'table') {
|
|
330
525
|
blocks.push(tableXml(el));
|
|
331
526
|
continue;
|
|
@@ -339,12 +534,17 @@
|
|
|
339
534
|
blocks.push(gridXml);
|
|
340
535
|
continue;
|
|
341
536
|
}
|
|
537
|
+
const flexXml = await flexAsTable(el, bag);
|
|
538
|
+
if (flexXml) {
|
|
539
|
+
blocks.push(flexXml);
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
342
542
|
if (tag === 'p' || tag === 'div' || tag === 'section' || tag === 'li') {
|
|
343
543
|
const hasBlock = [...el.children].some((c) =>
|
|
344
|
-
/^(DIV|TABLE|SECTION|UL|OL|H1|H2|H3|H4|H5|H6)$/.test(c.tagName),
|
|
544
|
+
/^(DIV|TABLE|SECTION|UL|OL|H1|H2|H3|H4|H5|H6|X-IMPORT)$/.test(c.tagName),
|
|
345
545
|
);
|
|
346
546
|
if (hasBlock && tag !== 'p') {
|
|
347
|
-
visit([...el.children]);
|
|
547
|
+
await visit([...el.children]);
|
|
348
548
|
} else {
|
|
349
549
|
const px = paraXml(el);
|
|
350
550
|
if (px) blocks.push(px);
|
|
@@ -352,13 +552,15 @@
|
|
|
352
552
|
continue;
|
|
353
553
|
}
|
|
354
554
|
if (tag === 'ul' || tag === 'ol') {
|
|
355
|
-
visit([...el.children]);
|
|
555
|
+
await visit([...el.children]);
|
|
356
556
|
continue;
|
|
357
557
|
}
|
|
358
|
-
|
|
558
|
+
const leftover = paraXml(el);
|
|
559
|
+
if (leftover) blocks.push(leftover);
|
|
560
|
+
else await visit([...el.children]);
|
|
359
561
|
}
|
|
360
562
|
};
|
|
361
|
-
visit([...sheet.children]);
|
|
563
|
+
await visit([...sheet.children]);
|
|
362
564
|
return blocks.filter(Boolean).join('');
|
|
363
565
|
}
|
|
364
566
|
|
|
@@ -372,12 +574,16 @@
|
|
|
372
574
|
const page = pageSizeFromCss();
|
|
373
575
|
const enc = new TextEncoder();
|
|
374
576
|
const { header, footer } = headerFooterText();
|
|
375
|
-
const
|
|
577
|
+
const bag = { media: [] };
|
|
578
|
+
const body = await sheetBodyXml(sheet, bag);
|
|
376
579
|
|
|
580
|
+
const pngDefault = bag.media.length
|
|
581
|
+
? `\n <Default Extension="png" ContentType="image/png"/>`
|
|
582
|
+
: '';
|
|
377
583
|
const contentTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
378
584
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
379
585
|
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
|
380
|
-
<Default Extension="xml" ContentType="application/xml"
|
|
586
|
+
<Default Extension="xml" ContentType="application/xml"/>${pngDefault}
|
|
381
587
|
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
|
|
382
588
|
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
|
|
383
589
|
<Override PartName="/word/header1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"/>
|
|
@@ -389,11 +595,18 @@
|
|
|
389
595
|
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
|
|
390
596
|
</Relationships>`;
|
|
391
597
|
|
|
598
|
+
const mediaRels = bag.media
|
|
599
|
+
.map(
|
|
600
|
+
(m) =>
|
|
601
|
+
` <Relationship Id="${m.relId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/${m.name.split('/').pop()}"/>`,
|
|
602
|
+
)
|
|
603
|
+
.join('\n');
|
|
392
604
|
const docRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
393
605
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
394
606
|
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
|
395
607
|
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml"/>
|
|
396
608
|
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer1.xml"/>
|
|
609
|
+
${mediaRels}
|
|
397
610
|
</Relationships>`;
|
|
398
611
|
|
|
399
612
|
const styles = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -424,14 +637,17 @@
|
|
|
424
637
|
|
|
425
638
|
const documentXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
426
639
|
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
427
|
-
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
640
|
+
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
641
|
+
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
|
|
642
|
+
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
|
|
643
|
+
xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
|
|
428
644
|
<w:body>
|
|
429
645
|
${body || '<w:p><w:r><w:t></w:t></w:r></w:p>'}
|
|
430
646
|
<w:sectPr>
|
|
431
647
|
<w:headerReference w:type="default" r:id="rId2"/>
|
|
432
648
|
<w:footerReference w:type="default" r:id="rId3"/>
|
|
433
649
|
<w:pgSz w:w="${page.w}" w:h="${page.h}"/>
|
|
434
|
-
<w:pgMar w:top="
|
|
650
|
+
<w:pgMar w:top="360" w:right="360" w:bottom="360" w:left="360" w:header="0" w:footer="0"/>
|
|
435
651
|
</w:sectPr>
|
|
436
652
|
</w:body>
|
|
437
653
|
</w:document>`;
|
|
@@ -444,6 +660,7 @@
|
|
|
444
660
|
{ name: 'word/styles.xml', bytes: enc.encode(styles) },
|
|
445
661
|
{ name: 'word/header1.xml', bytes: enc.encode(headerXml) },
|
|
446
662
|
{ name: 'word/footer1.xml', bytes: enc.encode(footerXml) },
|
|
663
|
+
...bag.media.map((m) => ({ name: m.name, bytes: m.bytes })),
|
|
447
664
|
]);
|
|
448
665
|
return new Blob([zip], {
|
|
449
666
|
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
@@ -500,7 +717,7 @@
|
|
|
500
717
|
return out;
|
|
501
718
|
}
|
|
502
719
|
|
|
503
|
-
function
|
|
720
|
+
function imagePagesToPdf(pages, mediaW, mediaH) {
|
|
504
721
|
const enc = new TextEncoder();
|
|
505
722
|
const nl = enc.encode('\n');
|
|
506
723
|
const chunks = [enc.encode('%PDF-1.4\n')];
|
|
@@ -532,10 +749,11 @@
|
|
|
532
749
|
pageId,
|
|
533
750
|
`<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${mediaW.toFixed(2)} ${mediaH.toFixed(2)}] /Resources << /XObject << /Im0 ${imgId} 0 R >> >> /Contents ${contentId} 0 R >>`,
|
|
534
751
|
);
|
|
752
|
+
const filter = page.filter || 'FlateDecode';
|
|
535
753
|
pushObj(
|
|
536
754
|
imgId,
|
|
537
|
-
`<< /Type /XObject /Subtype /Image /Width ${page.w} /Height ${page.h} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter
|
|
538
|
-
page.
|
|
755
|
+
`<< /Type /XObject /Subtype /Image /Width ${page.w} /Height ${page.h} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /${filter} /Length ${page.bytes.length} >>`,
|
|
756
|
+
page.bytes,
|
|
539
757
|
);
|
|
540
758
|
const contentBytes = enc.encode(content);
|
|
541
759
|
pushObj(contentId, `<< /Length ${contentBytes.length} >>`, contentBytes);
|
|
@@ -557,6 +775,27 @@
|
|
|
557
775
|
return concatBytes([body, enc.encode(xref), enc.encode(trailer)]);
|
|
558
776
|
}
|
|
559
777
|
|
|
778
|
+
function canvasRgb(ctx, w, h) {
|
|
779
|
+
const src = ctx.getImageData(0, 0, w, h).data;
|
|
780
|
+
const rgb = new Uint8Array(w * h * 3);
|
|
781
|
+
let j = 0;
|
|
782
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
783
|
+
rgb[j++] = src[i];
|
|
784
|
+
rgb[j++] = src[i + 1];
|
|
785
|
+
rgb[j++] = src[i + 2];
|
|
786
|
+
}
|
|
787
|
+
return rgb;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
async function deflateZlib(u8) {
|
|
791
|
+
const cs = new CompressionStream('deflate');
|
|
792
|
+
const writer = cs.writable.getWriter();
|
|
793
|
+
writer.write(u8);
|
|
794
|
+
writer.close();
|
|
795
|
+
const ab = await new Response(cs.readable).arrayBuffer();
|
|
796
|
+
return new Uint8Array(ab);
|
|
797
|
+
}
|
|
798
|
+
|
|
560
799
|
function relBox(el, origin, sheet) {
|
|
561
800
|
const r = el.getBoundingClientRect();
|
|
562
801
|
return {
|
|
@@ -679,9 +918,15 @@
|
|
|
679
918
|
|
|
680
919
|
async function rasterizeSheet(sheet) {
|
|
681
920
|
const page = pageSizeFromCss();
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
921
|
+
let scale = 3;
|
|
922
|
+
let painted;
|
|
923
|
+
try {
|
|
924
|
+
painted = await paintSheet(sheet, scale);
|
|
925
|
+
} catch (_) {
|
|
926
|
+
scale = 2;
|
|
927
|
+
painted = await paintSheet(sheet, scale);
|
|
928
|
+
}
|
|
929
|
+
const { canvas, ctx } = painted;
|
|
685
930
|
let ink = true;
|
|
686
931
|
try {
|
|
687
932
|
ink = canvasHasInk(ctx, canvas.width, Math.min(canvas.height, 400));
|
|
@@ -689,12 +934,26 @@
|
|
|
689
934
|
ink = true;
|
|
690
935
|
}
|
|
691
936
|
if (!ink) throw new Error('blank-raster');
|
|
692
|
-
// One PDF page = the whole card.
|
|
693
|
-
//
|
|
694
|
-
const jpeg = dataUrlToBytes(canvas.toDataURL('image/jpeg', 0.95));
|
|
937
|
+
// One PDF page = the whole card. Lossless Flate RGB (not JPEG) so type
|
|
938
|
+
// stays sharp; scale 3 ≈ 288 dpi on the A4-width MediaBox.
|
|
695
939
|
const ptW = page.ptW;
|
|
696
940
|
const ptH = ptW * (canvas.height / canvas.width);
|
|
697
|
-
|
|
941
|
+
try {
|
|
942
|
+
const rgb = canvasRgb(ctx, canvas.width, canvas.height);
|
|
943
|
+
const bytes = await deflateZlib(rgb);
|
|
944
|
+
return imagePagesToPdf(
|
|
945
|
+
[{ bytes, w: canvas.width, h: canvas.height, filter: 'FlateDecode' }],
|
|
946
|
+
ptW,
|
|
947
|
+
ptH,
|
|
948
|
+
);
|
|
949
|
+
} catch (_) {
|
|
950
|
+
const jpeg = dataUrlToBytes(canvas.toDataURL('image/jpeg', 0.95));
|
|
951
|
+
return imagePagesToPdf(
|
|
952
|
+
[{ bytes: jpeg, w: canvas.width, h: canvas.height, filter: 'DCTDecode' }],
|
|
953
|
+
ptW,
|
|
954
|
+
ptH,
|
|
955
|
+
);
|
|
956
|
+
}
|
|
698
957
|
}
|
|
699
958
|
|
|
700
959
|
async function buildPdfBlob(sheet) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"system": "CyberSkill Design System",
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.2",
|
|
5
5
|
"note": "OKLCH seed contract for the 15 element packs × light/dark (30 sets). SoT for scripts/generate-element-packs.mjs — do not hand-edit tokens/elements.css. Owner bar (Jul 2026): soft/middle/deep clearly distinct; middle intensity synced across elements; harmonious role palettes; light↔dark same-hue identity. Public variant names unchanged."
|
|
6
6
|
},
|
|
7
7
|
"intensity": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// CyberSkill Design System — native design tokens.
|
|
2
2
|
// GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
|
|
3
|
-
// release v1.7.
|
|
3
|
+
// release v1.7.2 · source sha256 1e71e4553ab540dd…
|
|
4
4
|
// conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
|
|
5
5
|
// dark element packs: see $extensions.overrides.elementsDark
|
|
6
6
|
// provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// CyberSkill Design System — native design tokens.
|
|
2
2
|
// GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
|
|
3
|
-
// release v1.7.
|
|
3
|
+
// release v1.7.2 · source sha256 1e71e4553ab540dd…
|
|
4
4
|
// conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
|
|
5
5
|
// dark element packs: see $extensions.overrides.elementsDark
|
|
6
6
|
// provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// CyberSkill Design System — native design tokens.
|
|
2
2
|
// GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
|
|
3
|
-
// release v1.7.
|
|
3
|
+
// release v1.7.2 · source sha256 1e71e4553ab540dd…
|
|
4
4
|
// conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
|
|
5
5
|
// dark element packs: see $extensions.overrides.elementsDark
|
|
6
6
|
// provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
|
package/tokens/provenance.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"system": "CyberSkill Design System",
|
|
3
|
-
"release": "1.7.
|
|
3
|
+
"release": "1.7.2",
|
|
4
4
|
"source": "tokens/tokens.dtcg.json",
|
|
5
|
-
"sourceSha256": "
|
|
5
|
+
"sourceSha256": "1e71e4553ab540dd0154ece1315b9a5148525ebdf7197d99400a6bc067b277c3",
|
|
6
6
|
"dtcgStamp": {
|
|
7
|
-
"version": "1.7.
|
|
7
|
+
"version": "1.7.2",
|
|
8
8
|
"generated": "2026-07-23"
|
|
9
9
|
},
|
|
10
10
|
"conversions": {
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
{
|
|
37
37
|
"file": "tokens/native/CSTokens.swift",
|
|
38
38
|
"lang": "swift",
|
|
39
|
-
"sha256": "
|
|
39
|
+
"sha256": "b4a7f3e5315bbb5de5469ea9b18e01906e739fd3d38c25d51026b30343509004"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"file": "tokens/native/CSTokens.kt",
|
|
43
43
|
"lang": "kotlin",
|
|
44
|
-
"sha256": "
|
|
44
|
+
"sha256": "662502acc441f711495ddb29a9129937b88466f337a365a7ed36bef11822cb8c"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"file": "tokens/native/cs_tokens.dart",
|
|
48
48
|
"lang": "dart",
|
|
49
|
-
"sha256": "
|
|
49
|
+
"sha256": "4bc9f7c849a82f8f5932c63b199d44d86d50868f8fc895a2980f77869b68cd19"
|
|
50
50
|
}
|
|
51
51
|
]
|
|
52
52
|
}
|
package/tokens/tokens.dtcg.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"$extensions": {
|
|
4
4
|
"com.cyberskill": {
|
|
5
5
|
"system": "CyberSkill Design System",
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.2",
|
|
7
7
|
"generated": "2026-07-23",
|
|
8
8
|
"source": "tokens/tokens.json",
|
|
9
9
|
"note": "Scope overrides (dark/system theme · 15 element×variant packs) are carried under $extensions.overrides keyed by CSS selector — apply the matching selector on :root/ancestor to activate.",
|
package/tokens/tokens.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// CyberSkill design tokens — generated from tokens/*.css (v1.7.
|
|
1
|
+
// CyberSkill design tokens — generated from tokens/*.css (v1.7.2). Do not edit by hand.
|
|
2
2
|
export const tokens = {
|
|
3
3
|
"$meta": {
|
|
4
4
|
"system": "CyberSkill Design System",
|
|
5
|
-
"version": "1.7.
|
|
5
|
+
"version": "1.7.2",
|
|
6
6
|
"generated": "2026-07-23",
|
|
7
7
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
8
8
|
},
|
package/tokens/tokens.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"system": "CyberSkill Design System",
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.2",
|
|
5
5
|
"generated": "2026-07-23",
|
|
6
6
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
7
7
|
},
|