@printwithsynergy/artwork-pdf-editor 0.1.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/LICENSE +62 -0
  2. package/README.md +63 -2
  3. package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
  4. package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
  5. package/dist/components/AccessibilityHintsPanel.js +158 -0
  6. package/dist/components/AccessibilityHintsPanel.js.map +1 -0
  7. package/dist/components/AnnotationOverlay.d.ts +142 -0
  8. package/dist/components/AnnotationOverlay.d.ts.map +1 -0
  9. package/dist/components/AnnotationOverlay.js +141 -0
  10. package/dist/components/AnnotationOverlay.js.map +1 -0
  11. package/dist/components/AnnotationsSidebar.d.ts +98 -0
  12. package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
  13. package/dist/components/AnnotationsSidebar.js +100 -0
  14. package/dist/components/AnnotationsSidebar.js.map +1 -0
  15. package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
  16. package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
  17. package/dist/components/BarcodeGeneratorPanel.js +91 -0
  18. package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
  19. package/dist/components/BraillePanel.d.ts +99 -0
  20. package/dist/components/BraillePanel.d.ts.map +1 -0
  21. package/dist/components/BraillePanel.js +221 -0
  22. package/dist/components/BraillePanel.js.map +1 -0
  23. package/dist/components/BrandAssetsPanel.d.ts +130 -0
  24. package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
  25. package/dist/components/BrandAssetsPanel.js +125 -0
  26. package/dist/components/BrandAssetsPanel.js.map +1 -0
  27. package/dist/components/BrandConsistencyPanel.d.ts +140 -0
  28. package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
  29. package/dist/components/BrandConsistencyPanel.js +158 -0
  30. package/dist/components/BrandConsistencyPanel.js.map +1 -0
  31. package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
  32. package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
  33. package/dist/components/ComplianceFindingsPanel.js +118 -0
  34. package/dist/components/ComplianceFindingsPanel.js.map +1 -0
  35. package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
  36. package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
  37. package/dist/components/DesignSuggestionsPanel.js +154 -0
  38. package/dist/components/DesignSuggestionsPanel.js.map +1 -0
  39. package/dist/components/DielineParametersPanel.d.ts +62 -0
  40. package/dist/components/DielineParametersPanel.d.ts.map +1 -0
  41. package/dist/components/DielineParametersPanel.js +170 -0
  42. package/dist/components/DielineParametersPanel.js.map +1 -0
  43. package/dist/components/DielinePreview.d.ts +150 -0
  44. package/dist/components/DielinePreview.d.ts.map +1 -0
  45. package/dist/components/DielinePreview.js +146 -0
  46. package/dist/components/DielinePreview.js.map +1 -0
  47. package/dist/components/EditorApp.d.ts +39 -5
  48. package/dist/components/EditorApp.d.ts.map +1 -1
  49. package/dist/components/EditorApp.js +110 -5
  50. package/dist/components/EditorApp.js.map +1 -1
  51. package/dist/components/EditorCanvas.d.ts +51 -2
  52. package/dist/components/EditorCanvas.d.ts.map +1 -1
  53. package/dist/components/EditorCanvas.js +117 -48
  54. package/dist/components/EditorCanvas.js.map +1 -1
  55. package/dist/components/EmailNotifyPanel.d.ts +165 -0
  56. package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
  57. package/dist/components/EmailNotifyPanel.js +211 -0
  58. package/dist/components/EmailNotifyPanel.js.map +1 -0
  59. package/dist/components/FileDropZone.d.ts +9 -1
  60. package/dist/components/FileDropZone.d.ts.map +1 -1
  61. package/dist/components/FileDropZone.js +53 -5
  62. package/dist/components/FileDropZone.js.map +1 -1
  63. package/dist/components/FoldEditorPanel.d.ts +68 -0
  64. package/dist/components/FoldEditorPanel.d.ts.map +1 -0
  65. package/dist/components/FoldEditorPanel.js +65 -0
  66. package/dist/components/FoldEditorPanel.js.map +1 -0
  67. package/dist/components/FoldPreviewOverlay.d.ts +48 -0
  68. package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
  69. package/dist/components/FoldPreviewOverlay.js +182 -0
  70. package/dist/components/FoldPreviewOverlay.js.map +1 -0
  71. package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
  72. package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
  73. package/dist/components/Gs1DigitalLinkPanel.js +199 -0
  74. package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
  75. package/dist/components/HistoryPanel.d.ts +39 -0
  76. package/dist/components/HistoryPanel.d.ts.map +1 -0
  77. package/dist/components/HistoryPanel.js +72 -0
  78. package/dist/components/HistoryPanel.js.map +1 -0
  79. package/dist/components/IccSoftProofOverlay.d.ts +67 -0
  80. package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
  81. package/dist/components/IccSoftProofOverlay.js +119 -0
  82. package/dist/components/IccSoftProofOverlay.js.map +1 -0
  83. package/dist/components/ImposePanel.d.ts +71 -0
  84. package/dist/components/ImposePanel.d.ts.map +1 -0
  85. package/dist/components/ImposePanel.js +127 -0
  86. package/dist/components/ImposePanel.js.map +1 -0
  87. package/dist/components/InksPanel.d.ts +61 -0
  88. package/dist/components/InksPanel.d.ts.map +1 -0
  89. package/dist/components/InksPanel.js +84 -0
  90. package/dist/components/InksPanel.js.map +1 -0
  91. package/dist/components/JobSetupPanel.d.ts +118 -0
  92. package/dist/components/JobSetupPanel.d.ts.map +1 -0
  93. package/dist/components/JobSetupPanel.js +169 -0
  94. package/dist/components/JobSetupPanel.js.map +1 -0
  95. package/dist/components/LayersPanel.d.ts.map +1 -1
  96. package/dist/components/LayersPanel.js +1 -0
  97. package/dist/components/LayersPanel.js.map +1 -1
  98. package/dist/components/MarkLibraryPanel.d.ts +131 -0
  99. package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
  100. package/dist/components/MarkLibraryPanel.js +184 -0
  101. package/dist/components/MarkLibraryPanel.js.map +1 -0
  102. package/dist/components/MisEstimateButton.d.ts +73 -0
  103. package/dist/components/MisEstimateButton.d.ts.map +1 -0
  104. package/dist/components/MisEstimateButton.js +57 -0
  105. package/dist/components/MisEstimateButton.js.map +1 -0
  106. package/dist/components/NutritionPanel.d.ts +118 -0
  107. package/dist/components/NutritionPanel.d.ts.map +1 -0
  108. package/dist/components/NutritionPanel.js +169 -0
  109. package/dist/components/NutritionPanel.js.map +1 -0
  110. package/dist/components/PageNavigator.d.ts +26 -0
  111. package/dist/components/PageNavigator.d.ts.map +1 -0
  112. package/dist/components/PageNavigator.js +96 -0
  113. package/dist/components/PageNavigator.js.map +1 -0
  114. package/dist/components/PaletteManager.d.ts +32 -0
  115. package/dist/components/PaletteManager.d.ts.map +1 -0
  116. package/dist/components/PaletteManager.js +89 -0
  117. package/dist/components/PaletteManager.js.map +1 -0
  118. package/dist/components/PaletteToSpotPanel.d.ts +122 -0
  119. package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
  120. package/dist/components/PaletteToSpotPanel.js +160 -0
  121. package/dist/components/PaletteToSpotPanel.js.map +1 -0
  122. package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
  123. package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
  124. package/dist/components/PreflightAutoFixPanel.js +119 -0
  125. package/dist/components/PreflightAutoFixPanel.js.map +1 -0
  126. package/dist/components/PreflightDiffPanel.d.ts +127 -0
  127. package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
  128. package/dist/components/PreflightDiffPanel.js +0 -0
  129. package/dist/components/PreflightDiffPanel.js.map +1 -0
  130. package/dist/components/ProcessRulesPanel.d.ts +81 -0
  131. package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
  132. package/dist/components/ProcessRulesPanel.js +143 -0
  133. package/dist/components/ProcessRulesPanel.js.map +1 -0
  134. package/dist/components/SlackNotifyPanel.d.ts +139 -0
  135. package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
  136. package/dist/components/SlackNotifyPanel.js +133 -0
  137. package/dist/components/SlackNotifyPanel.js.map +1 -0
  138. package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
  139. package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
  140. package/dist/components/SmartSpotMatchPanel.js +159 -0
  141. package/dist/components/SmartSpotMatchPanel.js.map +1 -0
  142. package/dist/components/SwatchesPicker.d.ts +83 -0
  143. package/dist/components/SwatchesPicker.d.ts.map +1 -0
  144. package/dist/components/SwatchesPicker.js +151 -0
  145. package/dist/components/SwatchesPicker.js.map +1 -0
  146. package/dist/components/TacOverlay.d.ts +47 -0
  147. package/dist/components/TacOverlay.d.ts.map +1 -0
  148. package/dist/components/TacOverlay.js +116 -0
  149. package/dist/components/TacOverlay.js.map +1 -0
  150. package/dist/components/TrapEditorPanel.d.ts +52 -0
  151. package/dist/components/TrapEditorPanel.d.ts.map +1 -0
  152. package/dist/components/TrapEditorPanel.js +64 -0
  153. package/dist/components/TrapEditorPanel.js.map +1 -0
  154. package/dist/components/TrapPreviewOverlay.d.ts +64 -0
  155. package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
  156. package/dist/components/TrapPreviewOverlay.js +120 -0
  157. package/dist/components/TrapPreviewOverlay.js.map +1 -0
  158. package/dist/components/VariantMatrixPanel.d.ts +61 -0
  159. package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
  160. package/dist/components/VariantMatrixPanel.js +97 -0
  161. package/dist/components/VariantMatrixPanel.js.map +1 -0
  162. package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
  163. package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
  164. package/dist/components/VariantMatrixVersionPanel.js +162 -0
  165. package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
  166. package/dist/components/WebhookNotifyPanel.d.ts +160 -0
  167. package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
  168. package/dist/components/WebhookNotifyPanel.js +100 -0
  169. package/dist/components/WebhookNotifyPanel.js.map +1 -0
  170. package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
  171. package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
  172. package/dist/components/WhiteUnderbasePanel.js +104 -0
  173. package/dist/components/WhiteUnderbasePanel.js.map +1 -0
  174. package/dist/data/dielines.json +35 -0
  175. package/dist/hooks/useEditorMode.d.ts +25 -5
  176. package/dist/hooks/useEditorMode.d.ts.map +1 -1
  177. package/dist/hooks/useEditorMode.js +18 -5
  178. package/dist/hooks/useEditorMode.js.map +1 -1
  179. package/dist/index.d.ts +49 -2
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +49 -2
  182. package/dist/index.js.map +1 -1
  183. package/dist/lens/dieline-overlay.d.ts +25 -0
  184. package/dist/lens/dieline-overlay.d.ts.map +1 -0
  185. package/dist/lens/dieline-overlay.js +50 -0
  186. package/dist/lens/dieline-overlay.js.map +1 -0
  187. package/dist/lens/index.d.ts +27 -0
  188. package/dist/lens/index.d.ts.map +1 -0
  189. package/dist/lens/index.js +28 -0
  190. package/dist/lens/index.js.map +1 -0
  191. package/dist/lens/preflight-findings.d.ts +21 -0
  192. package/dist/lens/preflight-findings.d.ts.map +1 -0
  193. package/dist/lens/preflight-findings.js +82 -0
  194. package/dist/lens/preflight-findings.js.map +1 -0
  195. package/dist/lib/barcode-scan.d.ts +154 -0
  196. package/dist/lib/barcode-scan.d.ts.map +1 -0
  197. package/dist/lib/barcode-scan.js +152 -0
  198. package/dist/lib/barcode-scan.js.map +1 -0
  199. package/dist/lib/color-math.d.ts +76 -0
  200. package/dist/lib/color-math.d.ts.map +1 -0
  201. package/dist/lib/color-math.js +96 -0
  202. package/dist/lib/color-math.js.map +1 -0
  203. package/dist/lib/dieline-template.d.ts +169 -0
  204. package/dist/lib/dieline-template.d.ts.map +1 -1
  205. package/dist/lib/dieline-template.js +229 -1
  206. package/dist/lib/dieline-template.js.map +1 -1
  207. package/dist/lib/editor-config.d.ts +384 -1
  208. package/dist/lib/editor-config.d.ts.map +1 -1
  209. package/dist/lib/editor-config.js +89 -2
  210. package/dist/lib/editor-config.js.map +1 -1
  211. package/dist/lib/fold-geometry.d.ts +144 -0
  212. package/dist/lib/fold-geometry.d.ts.map +1 -0
  213. package/dist/lib/fold-geometry.js +138 -0
  214. package/dist/lib/fold-geometry.js.map +1 -0
  215. package/dist/lib/merge-tokens.d.ts +81 -0
  216. package/dist/lib/merge-tokens.d.ts.map +1 -0
  217. package/dist/lib/merge-tokens.js +88 -0
  218. package/dist/lib/merge-tokens.js.map +1 -0
  219. package/dist/lib/palette-registry.d.ts +40 -0
  220. package/dist/lib/palette-registry.d.ts.map +1 -0
  221. package/dist/lib/palette-registry.js +49 -0
  222. package/dist/lib/palette-registry.js.map +1 -0
  223. package/dist/lib/panel-anchor.d.ts +101 -0
  224. package/dist/lib/panel-anchor.d.ts.map +1 -0
  225. package/dist/lib/panel-anchor.js +68 -0
  226. package/dist/lib/panel-anchor.js.map +1 -0
  227. package/dist/lib/preflight/checks.d.ts.map +1 -1
  228. package/dist/lib/preflight/checks.js +71 -0
  229. package/dist/lib/preflight/checks.js.map +1 -1
  230. package/dist/lib/preflight/types.d.ts.map +1 -1
  231. package/dist/lib/preflight/types.js +11 -0
  232. package/dist/lib/preflight/types.js.map +1 -1
  233. package/dist/lib/rasterize.d.ts +93 -0
  234. package/dist/lib/rasterize.d.ts.map +1 -0
  235. package/dist/lib/rasterize.js +117 -0
  236. package/dist/lib/rasterize.js.map +1 -0
  237. package/dist/lib/separations-registry.d.ts +99 -0
  238. package/dist/lib/separations-registry.d.ts.map +1 -0
  239. package/dist/lib/separations-registry.js +59 -0
  240. package/dist/lib/separations-registry.js.map +1 -0
  241. package/dist/lib/unwired.d.ts +29 -0
  242. package/dist/lib/unwired.d.ts.map +1 -0
  243. package/dist/lib/unwired.js +58 -0
  244. package/dist/lib/unwired.js.map +1 -0
  245. package/package.json +29 -11
  246. package/dist/components/SeparationsPanel.d.ts +0 -9
  247. package/dist/components/SeparationsPanel.d.ts.map +0 -1
  248. package/dist/components/SeparationsPanel.js +0 -168
  249. package/dist/components/SeparationsPanel.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,62 @@
1
+ artworkPDF — WYSIWYG label & packaging artwork editor
2
+ Copyright (C) 2024-2026 Think Neverland LLC
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public
15
+ License along with this program. If not, see
16
+ <https://www.gnu.org/licenses/>.
17
+
18
+ ---
19
+
20
+ GNU AFFERO GENERAL PUBLIC LICENSE
21
+ Version 3, 19 November 2007
22
+
23
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
24
+ Everyone is permitted to copy and distribute verbatim copies
25
+ of this license document, but changing it is not allowed.
26
+
27
+ Preamble
28
+
29
+ The GNU Affero General Public License is a free, copyleft license for
30
+ software and other kinds of works, specifically designed to ensure
31
+ cooperation with the community in the case of network server software.
32
+
33
+ The licenses for most software and other practical works are designed
34
+ to take away your freedom to share and change the works. By contrast,
35
+ our General Public Licenses are intended to guarantee your freedom to
36
+ share and change all versions of a program--to make sure it remains free
37
+ software for all its users.
38
+
39
+ When we speak of free software, we are referring to freedom, not
40
+ price. Our General Public Licenses are designed to make sure that you
41
+ have the freedom to distribute copies of free software (and charge for
42
+ them if you wish), to help you ensure that you receive source code or can
43
+ get it if you want it, to help you ensure that you can give other people
44
+ a copy of it, and let you know you can do these things.
45
+
46
+ Developers that use our General Public Licenses protect your rights
47
+ with two steps: (1) assert copyright on the software, and (2) offer
48
+ you this License which gives you legal permission to copy, distribute
49
+ and/or modify the software.
50
+
51
+ A secondary benefit of defending all users' freedom is that
52
+ improvements made in individual component, which are widely deployed on
53
+ network servers, become available to improve those servers too. Whether
54
+ this happens depends on what the server software does with the
55
+ modifications made in it. The GNU Affero General Public License
56
+ requires that modified source code be made available to the users.
57
+ In the case of a network server, this is relatively easy to achieve.
58
+
59
+ The precise terms and conditions for copying, distribution and
60
+ modification follow.
61
+
62
+ See <https://www.gnu.org/licenses/agpl-3.0.txt> for the full license text.
package/README.md CHANGED
@@ -70,7 +70,6 @@ Defaults to everything enabled.
70
70
  ```tsx
71
71
  <EditorApp
72
72
  config={{
73
- enable_separations_panel: false,
74
73
  enable_layers_panel: false,
75
74
  enable_source_link: false,
76
75
  }}
@@ -109,7 +108,69 @@ import { getTemplateById } from "@printwithsynergy/artwork-pdf-editor";
109
108
  const tpl = getTemplateById("standup-pouch-4x6");
110
109
  ```
111
110
 
112
- Hosted routes can deep-link with `?dieline=<id>`.
111
+ Hosted routes can deep-link with `?dieline=<id>`. The demo route also
112
+ accepts:
113
+
114
+ - A bundled multi-page set id (`?dieline=carton-6x4x2-set`) — see
115
+ `TEMPLATE_SETS`.
116
+ - A comma-separated list of template ids
117
+ (`?dieline=carton-6x4x2,carton-6x4x2`).
118
+
119
+ Unknown ids silently fall back to the default template.
120
+
121
+ ## Multi-page documents
122
+
123
+ Each page in a multi-page artwork carries its own `objects`, `pageSize`,
124
+ `bleedMm`, and optional `templateId` + `name`. Seed via `initialPages`:
125
+
126
+ ```tsx
127
+ import {
128
+ EditorApp,
129
+ getTemplateSetById,
130
+ templateSetToPages,
131
+ } from "@printwithsynergy/artwork-pdf-editor";
132
+
133
+ const set = getTemplateSetById("carton-6x4x2-set");
134
+ const pages = templateSetToPages(set!, 3.175); // 0.125 in bleed
135
+
136
+ <EditorApp demo initialPhase="editor" initialPages={pages} />
137
+ ```
138
+
139
+ Helpers:
140
+
141
+ - `templateToPage(template, bleedMm?, name?)` — single template → Page.
142
+ - `templatesToPages([{ template, name }], bleedMm?)` — ordered ad-hoc
143
+ set → Page[].
144
+ - `templateSetToPages(set, bleedMm?)` — bundled set → Page[].
145
+
146
+ A `PageNavigator` strip renders above the canvas on desktop and a
147
+ "Pages" section appears in the mobile drawer. Users can switch
148
+ between pages, add (duplicate) pages, and delete pages. Per-page state
149
+ is preserved across switches; each page has its own undo history.
150
+
151
+ ## Lens plugins (`/lens` subpath)
152
+
153
+ Hosts that mount [`@printwithsynergy/lens-pdf`](https://www.npmjs.com/package/@printwithsynergy/lens-pdf)
154
+ to display rendered output can register artwork-aware overlays:
155
+
156
+ ```tsx
157
+ import { LensPDF } from "@printwithsynergy/lens-pdf";
158
+ import {
159
+ dielineOverlayPlugin,
160
+ preflightFindingsPlugin,
161
+ } from "@printwithsynergy/artwork-pdf-editor/lens";
162
+
163
+ <LensPDF
164
+ pdfUrl={blobUrl}
165
+ plugins={[
166
+ dielineOverlayPlugin({ pages: { 1: { template: tpl, bleedMm: 3.175 } } }),
167
+ preflightFindingsPlugin({ report }),
168
+ ]}
169
+ />
170
+ ```
171
+
172
+ `@printwithsynergy/lens-pdf` is an **optional** peer dep — only required
173
+ when you import from the `/lens` subpath.
113
174
 
114
175
  ## License
115
176
 
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Wave 4 AI5 — Accessibility hints panel.
3
+ *
4
+ * Fourth panel in the Wave 4 AI family alongside AI1
5
+ * {@link DesignSuggestionsPanel} (proactive design hints), AI2
6
+ * {@link SmartSpotMatchPanel} (ΔE-ranked PANTONE matcher), and AI3
7
+ * {@link PreflightAutoFixPanel} (preflight remediation). AI5 surfaces
8
+ * accessibility findings (low contrast, missing alt text, text-size
9
+ * minimums, color-only signalling) sourced from a host-supplied
10
+ * loader. Rules-engine, ML adapter, or a tenant-deployed lint-pdf
11
+ * accessibility profile all fit the same loader contract.
12
+ *
13
+ * Findings carry an optional `objectId` so the host can scroll the
14
+ * offending canvas object into view, and an optional `severity` for
15
+ * triage. The same three-tier severity vocabulary as B2
16
+ * BrandConsistencyPanel — kept identical on purpose so a single host
17
+ * triage UI can render both panels' rows the same way.
18
+ *
19
+ * @public
20
+ */
21
+ import type { ReactElement } from "react";
22
+ /**
23
+ * Severity of an accessibility finding. Mirrors B2's vocabulary
24
+ * verbatim so hosts that surface both panels in one triage list get
25
+ * consistent ordering and colors.
26
+ *
27
+ * @public
28
+ */
29
+ export type AccessibilitySeverity = "error" | "warn" | "info";
30
+ /**
31
+ * Category an accessibility finding belongs to. Hosts can render
32
+ * category chips for quick scanning; the panel groups findings by
33
+ * severity, not category.
34
+ *
35
+ * @public
36
+ */
37
+ export type AccessibilityCategory = "contrast" | "alt-text" | "text-size" | "color-only" | "structure" | "other";
38
+ /**
39
+ * One accessibility finding. The optional `recommendation` is a
40
+ * single short remediation hint surfaced as a secondary line in the
41
+ * row; the optional `objectId` lets the host wire a focus / scroll
42
+ * affordance to the offending canvas object.
43
+ *
44
+ * @public
45
+ */
46
+ export type AccessibilityFinding = {
47
+ /** Stable identifier — the panel uses it as the React key and
48
+ * exposes it through `onSelect`. */
49
+ id: string;
50
+ category: AccessibilityCategory;
51
+ severity: AccessibilitySeverity;
52
+ summary: string;
53
+ /** Optional short remediation hint (one line). */
54
+ recommendation?: string;
55
+ /** Optional id of the canvas object the finding applies to. */
56
+ objectId?: string;
57
+ };
58
+ /**
59
+ * Host adapter — resolves the full accessibility finding list for the
60
+ * active document. Rejects on transport / validation errors and the
61
+ * panel surfaces the message inline. Hosts should memoize the
62
+ * function with `useCallback` so an unrelated parent re-render doesn't
63
+ * trigger a spurious refetch.
64
+ *
65
+ * @public
66
+ */
67
+ export type AccessibilityHintsLoaderFn = () => Promise<readonly AccessibilityFinding[]>;
68
+ /**
69
+ * Filter spec accepted by {@link filterAccessibilityFindings}.
70
+ *
71
+ * @public
72
+ */
73
+ export type AccessibilityFilter = {
74
+ /** Pre-filter to a single severity. Absent → all severities. */
75
+ severity?: AccessibilitySeverity;
76
+ /** Pre-filter to a single category. Absent → all categories. */
77
+ category?: AccessibilityCategory;
78
+ };
79
+ /**
80
+ * Result row from {@link groupAccessibilityFindingsBySeverity}.
81
+ *
82
+ * @public
83
+ */
84
+ export type AccessibilityGroup = {
85
+ severity: AccessibilitySeverity;
86
+ findings: readonly AccessibilityFinding[];
87
+ };
88
+ /**
89
+ * Canonical severity order — errors first so press-blocking issues
90
+ * surface at the top. Identical to B2's order on purpose.
91
+ *
92
+ * @public
93
+ */
94
+ export declare const ACCESSIBILITY_SEVERITY_ORDER: readonly AccessibilitySeverity[];
95
+ /**
96
+ * Pure helper — filters findings by severity / category. Returns a
97
+ * new array; preserves input order. Pure function.
98
+ *
99
+ * @public
100
+ */
101
+ export declare function filterAccessibilityFindings(findings: readonly AccessibilityFinding[], filter: AccessibilityFilter): readonly AccessibilityFinding[];
102
+ /**
103
+ * Pure helper — groups findings by severity in
104
+ * {@link ACCESSIBILITY_SEVERITY_ORDER}. Returns a stable three-bucket
105
+ * shape so renderers iterate without absent-key checks.
106
+ *
107
+ * Pure function.
108
+ *
109
+ * @public
110
+ */
111
+ export declare function groupAccessibilityFindingsBySeverity(findings: readonly AccessibilityFinding[]): readonly AccessibilityGroup[];
112
+ /**
113
+ * Configuration for the {@link AccessibilityHintsPanel}. The host
114
+ * always supplies the {@link AccessibilityHintsLoaderFn}; the
115
+ * optional `onSelect` callback lets the host wire a focus affordance
116
+ * (jump to the offending canvas object, focus the matching property
117
+ * editor row, etc.).
118
+ *
119
+ * @public
120
+ */
121
+ export type AccessibilityHintsPanelProps = {
122
+ loader: AccessibilityHintsLoaderFn;
123
+ /** Optional severity pre-filter applied before grouping. */
124
+ filterSeverity?: AccessibilitySeverity;
125
+ /** Optional category pre-filter applied before grouping. */
126
+ filterCategory?: AccessibilityCategory;
127
+ /** Id of the currently active finding — the matching row renders
128
+ * in the "active" style. Hosts wire this to whichever surface
129
+ * drives selection. */
130
+ activeFindingId?: string;
131
+ /** Fired when the user clicks a row. */
132
+ onSelect?: (finding: AccessibilityFinding) => void;
133
+ };
134
+ /**
135
+ * Stateful panel — loads the finding stream on mount, surfaces the
136
+ * filtered + grouped list, and emits `onSelect` on row click.
137
+ * Handles loading / error / empty states inline.
138
+ *
139
+ * @public
140
+ */
141
+ export declare function AccessibilityHintsPanel({ loader, filterSeverity, filterCategory, activeFindingId, onSelect, }: AccessibilityHintsPanelProps): ReactElement;
142
+ //# sourceMappingURL=AccessibilityHintsPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessibilityHintsPanel.d.ts","sourceRoot":"","sources":["../../src/components/AccessibilityHintsPanel.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAC7B,UAAU,GACV,UAAU,GACV,WAAW,GACX,YAAY,GACZ,WAAW,GACX,OAAO,CAAC;AAEZ;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;yCACqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,qBAAqB,CAAC;IAChC,QAAQ,EAAE,qBAAqB,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,0BAA0B,GAAG,MAAM,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CAAC;AAExF;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,qBAAqB,EAIxE,CAAC;AAcF;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,MAAM,EAAE,mBAAmB,GAC1B,SAAS,oBAAoB,EAAE,CAMjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GACxC,SAAS,kBAAkB,EAAE,CAW/B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC,MAAM,EAAE,0BAA0B,CAAC;IACnC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC;;4BAEwB;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,cAAc,EACd,cAAc,EACd,eAAe,EACf,QAAQ,GACT,EAAE,4BAA4B,GAAG,YAAY,CA8G7C"}
@@ -0,0 +1,158 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ "use client";
3
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
+ import { useEffect, useMemo, useState } from "react";
5
+ /**
6
+ * Canonical severity order — errors first so press-blocking issues
7
+ * surface at the top. Identical to B2's order on purpose.
8
+ *
9
+ * @public
10
+ */
11
+ export const ACCESSIBILITY_SEVERITY_ORDER = [
12
+ "error",
13
+ "warn",
14
+ "info",
15
+ ];
16
+ const SEVERITY_LABELS = {
17
+ error: "Errors",
18
+ warn: "Warnings",
19
+ info: "Info",
20
+ };
21
+ const SEVERITY_COLORS = {
22
+ error: "#a00",
23
+ warn: "#a60",
24
+ info: "#06a",
25
+ };
26
+ /**
27
+ * Pure helper — filters findings by severity / category. Returns a
28
+ * new array; preserves input order. Pure function.
29
+ *
30
+ * @public
31
+ */
32
+ export function filterAccessibilityFindings(findings, filter) {
33
+ return findings.filter((f) => {
34
+ if (filter.severity && f.severity !== filter.severity)
35
+ return false;
36
+ if (filter.category && f.category !== filter.category)
37
+ return false;
38
+ return true;
39
+ });
40
+ }
41
+ /**
42
+ * Pure helper — groups findings by severity in
43
+ * {@link ACCESSIBILITY_SEVERITY_ORDER}. Returns a stable three-bucket
44
+ * shape so renderers iterate without absent-key checks.
45
+ *
46
+ * Pure function.
47
+ *
48
+ * @public
49
+ */
50
+ export function groupAccessibilityFindingsBySeverity(findings) {
51
+ const buckets = new Map(ACCESSIBILITY_SEVERITY_ORDER.map((s) => [s, []]));
52
+ for (const f of findings) {
53
+ buckets.get(f.severity)?.push(f);
54
+ }
55
+ return ACCESSIBILITY_SEVERITY_ORDER.map((severity) => ({
56
+ severity,
57
+ findings: buckets.get(severity) ?? [],
58
+ }));
59
+ }
60
+ /**
61
+ * Stateful panel — loads the finding stream on mount, surfaces the
62
+ * filtered + grouped list, and emits `onSelect` on row click.
63
+ * Handles loading / error / empty states inline.
64
+ *
65
+ * @public
66
+ */
67
+ export function AccessibilityHintsPanel({ loader, filterSeverity, filterCategory, activeFindingId, onSelect, }) {
68
+ const [findings, setFindings] = useState(null);
69
+ const [error, setError] = useState(null);
70
+ const [loading, setLoading] = useState(true);
71
+ useEffect(() => {
72
+ let disposed = false;
73
+ setLoading(true);
74
+ setError(null);
75
+ setFindings(null);
76
+ void (async () => {
77
+ try {
78
+ const next = await loader();
79
+ if (disposed)
80
+ return;
81
+ setFindings(next);
82
+ }
83
+ catch (err) {
84
+ if (disposed)
85
+ return;
86
+ setError(err instanceof Error ? err.message : String(err));
87
+ }
88
+ finally {
89
+ if (!disposed)
90
+ setLoading(false);
91
+ }
92
+ })();
93
+ return () => {
94
+ disposed = true;
95
+ };
96
+ }, [loader]);
97
+ const visibleGroups = useMemo(() => {
98
+ if (!findings)
99
+ return null;
100
+ const filtered = filterAccessibilityFindings(findings, {
101
+ ...(filterSeverity && { severity: filterSeverity }),
102
+ ...(filterCategory && { category: filterCategory }),
103
+ });
104
+ return groupAccessibilityFindingsBySeverity(filtered);
105
+ }, [findings, filterSeverity, filterCategory]);
106
+ if (loading) {
107
+ return (_jsx("output", { "data-testid": "accessibility-hints-panel", "aria-live": "polite", style: { display: "block", padding: "0.5rem", opacity: 0.6 }, children: "Loading accessibility hints\u2026" }));
108
+ }
109
+ if (error) {
110
+ return (_jsxs("div", { "data-testid": "accessibility-hints-panel", role: "alert", style: { padding: "0.5rem", color: "#a00" }, children: ["Couldn't load accessibility hints: ", error] }));
111
+ }
112
+ if (!visibleGroups)
113
+ return _jsx("div", { "data-testid": "accessibility-hints-panel" });
114
+ const totalVisible = visibleGroups.reduce((s, g) => s + g.findings.length, 0);
115
+ return (_jsxs("div", { "data-testid": "accessibility-hints-panel", style: { padding: "0.5rem" }, children: [_jsx("header", { style: { marginBottom: "0.5rem" }, children: _jsxs("h3", { style: { margin: 0, fontSize: "0.875rem" }, children: ["Accessibility hints (", totalVisible, ")"] }) }), totalVisible === 0 && (_jsx("div", { "data-testid": "accessibility-hints-panel-empty", style: { opacity: 0.6, fontSize: "0.875rem" }, children: findings && findings.length > 0
116
+ ? "No findings match the current filter."
117
+ : "No accessibility issues detected." })), visibleGroups.map((group) => {
118
+ if (group.findings.length === 0)
119
+ return null;
120
+ return (_jsxs("section", { "data-testid": `accessibility-hints-group-${group.severity}`, style: { marginBottom: "0.75rem" }, children: [_jsxs("h4", { style: {
121
+ margin: "0 0 0.25rem 0",
122
+ fontSize: "0.75rem",
123
+ color: SEVERITY_COLORS[group.severity],
124
+ textTransform: "uppercase",
125
+ letterSpacing: "0.05em",
126
+ }, children: [SEVERITY_LABELS[group.severity], " (", group.findings.length, ")"] }), _jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: group.findings.map((finding) => (_jsx(AccessibilityRow, { finding: finding, isActive: finding.id === activeFindingId, onSelect: onSelect }, finding.id))) })] }, group.severity));
127
+ })] }));
128
+ }
129
+ /**
130
+ * Renders one finding row. Intra-package helper — surface
131
+ * (category chip, summary, optional recommendation) is intentionally
132
+ * minimal so {@link AccessibilityHintsPanel} can swap it without
133
+ * downstream consumers depending on the shape.
134
+ */
135
+ function AccessibilityRow({ finding, isActive, onSelect, }) {
136
+ const rowStyle = {
137
+ display: "block",
138
+ width: "100%",
139
+ padding: "0.375rem 0.5rem",
140
+ background: isActive ? "#e0ecff" : "transparent",
141
+ border: isActive ? "1px solid #2563eb" : "1px solid #ddd",
142
+ borderRadius: 4,
143
+ marginBottom: "0.25rem",
144
+ textAlign: "left",
145
+ cursor: onSelect ? "pointer" : "default",
146
+ };
147
+ const contents = (_jsxs(_Fragment, { children: [_jsxs("div", { style: { fontSize: "0.8125rem", fontWeight: 500 }, children: [_jsx("span", { style: {
148
+ display: "inline-block",
149
+ fontSize: "0.625rem",
150
+ padding: "0.0625rem 0.375rem",
151
+ borderRadius: 999,
152
+ background: "#eee",
153
+ color: "#595959",
154
+ marginRight: "0.375rem",
155
+ }, children: finding.category }), finding.summary] }), finding.recommendation && (_jsx("div", { style: { fontSize: "0.75rem", color: "#595959", marginTop: "0.125rem" }, children: finding.recommendation }))] }));
156
+ return (_jsx("li", { children: onSelect ? (_jsx("button", { type: "button", onClick: () => onSelect(finding), style: rowStyle, children: contents })) : (_jsx("div", { style: rowStyle, children: contents })) }));
157
+ }
158
+ //# sourceMappingURL=AccessibilityHintsPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessibilityHintsPanel.js","sourceRoot":"","sources":["../../src/components/AccessibilityHintsPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Wave 4 X3 — Annotation overlay.
3
+ *
4
+ * Renders pinned author annotations from `PageV3.annotations` on top
5
+ * of the canvas. Three kinds, discriminated by `kind`:
6
+ * - `"point"` — anchor pin with optional note
7
+ * - `"area"` — bounded rectangle with optional note
8
+ * - `"text"` — anchor pin with a required text body
9
+ *
10
+ * Pure controlled SVG overlay. No state, no DOM events beyond an
11
+ * optional `onSelect` click — the host owns selection / hover /
12
+ * popover UI and writes back to `document.pages[i].annotations`.
13
+ *
14
+ * Pairs with the discriminated union in `@artworkpdf/document-model`'s
15
+ * `Annotation` type. The component duplicates the wire shape locally
16
+ * (same pattern as `BrandAsset` / `PreflightFinding`) so the editor
17
+ * stays consumable without the doc-model SDK.
18
+ *
19
+ * @public
20
+ */
21
+ import type { ReactElement } from "react";
22
+ /**
23
+ * Fields shared by every annotation variant. Mirrors document-model's
24
+ * internal `AnnotationBase` shape.
25
+ *
26
+ * @public
27
+ */
28
+ export type AnnotationBaseInput = {
29
+ id: string;
30
+ x: number;
31
+ y: number;
32
+ author?: string;
33
+ createdAt: string;
34
+ resolved?: boolean;
35
+ };
36
+ /**
37
+ * Pinpoint annotation — single x/y marker with an optional note.
38
+ * Width / height are forbidden by the union discrimination.
39
+ *
40
+ * @public
41
+ */
42
+ export type PointAnnotationInput = AnnotationBaseInput & {
43
+ kind: "point";
44
+ text?: string;
45
+ };
46
+ /**
47
+ * Bounded-region annotation. `width` / `height` define a rectangle
48
+ * anchored at (`x`, `y`) in page coordinates. `text` is the optional
49
+ * note body.
50
+ *
51
+ * @public
52
+ */
53
+ export type AreaAnnotationInput = AnnotationBaseInput & {
54
+ kind: "area";
55
+ width: number;
56
+ height: number;
57
+ text?: string;
58
+ };
59
+ /**
60
+ * Inline text annotation — anchor pin with a required text body.
61
+ * Use {@link PointAnnotationInput} when the note is optional.
62
+ *
63
+ * @public
64
+ */
65
+ export type TextAnnotationInput = AnnotationBaseInput & {
66
+ kind: "text";
67
+ text: string;
68
+ };
69
+ /**
70
+ * One annotation, discriminated on `kind`. Structurally compatible
71
+ * with document-model's `Annotation` union.
72
+ *
73
+ * @public
74
+ */
75
+ export type AnnotationOverlayAnnotation = PointAnnotationInput | AreaAnnotationInput | TextAnnotationInput;
76
+ /**
77
+ * @public
78
+ */
79
+ export type AnnotationOverlayProps = {
80
+ /** Annotations to render. Typically `PageV3.annotations ?? []`. */
81
+ annotations: readonly AnnotationOverlayAnnotation[];
82
+ /** Width of the underlying page in CSS pixels. The SVG overlay
83
+ * matches the host's page-rendering surface so annotation anchors
84
+ * land where the user placed them. */
85
+ pageWidthPx: number;
86
+ /** Height of the underlying page in CSS pixels. */
87
+ pageHeightPx: number;
88
+ /** When `true`, also render annotations whose `resolved` flag is
89
+ * `true`. Absent / `false`: resolved annotations are hidden so
90
+ * the canvas stays focused on open conversations. */
91
+ showResolved?: boolean;
92
+ /** Id of the annotation to render in the "active" style (host-
93
+ * controlled hover / selection affordance). */
94
+ activeAnnotationId?: string;
95
+ /** Optional click callback. Hosts wire it to open their own
96
+ * popover / sidebar showing the annotation body, author, etc. */
97
+ onSelect?: (annotation: AnnotationOverlayAnnotation) => void;
98
+ };
99
+ /**
100
+ * Build a screen-reader-friendly description of an annotation.
101
+ *
102
+ * Pattern: `"<status> <kind> annotation[: <truncated body>]"`. The
103
+ * resolved status comes first so screen readers announce it ahead of
104
+ * the body (matching the visual cue: greyed-out marker = resolved).
105
+ * Body text is truncated to 60 chars so long comments don't blow up
106
+ * the announcement. The internal `id` is intentionally omitted —
107
+ * opaque ids carry no meaning for assistive tech.
108
+ *
109
+ * Pure function; exposed so hosts that render their own annotation
110
+ * affordances (e.g. a sidebar list) can describe rows consistently
111
+ * with the overlay's pin labels.
112
+ *
113
+ * @public
114
+ */
115
+ export declare function describeAnnotation(annotation: AnnotationOverlayAnnotation): string;
116
+ /**
117
+ * Filter resolved annotations unless `showResolved` is set. Pure
118
+ * function; exposed for hosts that drive their own renderer.
119
+ *
120
+ * @public
121
+ */
122
+ export declare function visibleAnnotations(annotations: readonly AnnotationOverlayAnnotation[], showResolved: boolean): readonly AnnotationOverlayAnnotation[];
123
+ /**
124
+ * Hit-test an annotation at a point. Point / text annotations use a
125
+ * circular hit zone of {@link HIT_RADIUS_PX} around `(x, y)`; area
126
+ * annotations use the inclusive bounding rectangle. Pure function;
127
+ * exposed so hosts can hit-test against the same algorithm the
128
+ * overlay uses for click handling.
129
+ *
130
+ * @public
131
+ */
132
+ export declare function isPointInsideAnnotation(annotation: AnnotationOverlayAnnotation, px: number, py: number): boolean;
133
+ /**
134
+ * Renders the annotation layer as an absolutely-positioned SVG over
135
+ * the page surface. Pointer events propagate through transparent
136
+ * areas; hosts can stack the overlay over interactive layers without
137
+ * blocking selection of canvas objects.
138
+ *
139
+ * @public
140
+ */
141
+ export declare function AnnotationOverlay({ annotations, pageWidthPx, pageHeightPx, showResolved, activeAnnotationId, onSelect, }: AnnotationOverlayProps): ReactElement;
142
+ //# sourceMappingURL=AnnotationOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnnotationOverlay.d.ts","sourceRoot":"","sources":["../../src/components/AnnotationOverlay.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,GAAG;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,GAAG;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GACnC,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,mEAAmE;IACnE,WAAW,EAAE,SAAS,2BAA2B,EAAE,CAAC;IACpD;;2CAEuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB;;0DAEsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;oDACgD;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;sEACkE;IAClE,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;AAsBF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,2BAA2B,GAAG,MAAM,CAOlF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,SAAS,2BAA2B,EAAE,EACnD,YAAY,EAAE,OAAO,GACpB,SAAS,2BAA2B,EAAE,CAGxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,2BAA2B,EACvC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,OAAO,CAYT;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,QAAQ,GACT,EAAE,sBAAsB,GAAG,YAAY,CAsCvC"}