@furystack/shades 11.0.35 → 12.0.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 (215) hide show
  1. package/CHANGELOG.md +337 -0
  2. package/README.md +99 -13
  3. package/esm/compile-route.spec.d.ts +2 -0
  4. package/esm/compile-route.spec.d.ts.map +1 -0
  5. package/esm/compile-route.spec.js +34 -0
  6. package/esm/compile-route.spec.js.map +1 -0
  7. package/esm/component-factory.spec.js +13 -5
  8. package/esm/component-factory.spec.js.map +1 -1
  9. package/esm/components/index.d.ts +4 -1
  10. package/esm/components/index.d.ts.map +1 -1
  11. package/esm/components/index.js +4 -1
  12. package/esm/components/index.js.map +1 -1
  13. package/esm/components/lazy-load.d.ts +2 -4
  14. package/esm/components/lazy-load.d.ts.map +1 -1
  15. package/esm/components/lazy-load.js +40 -24
  16. package/esm/components/lazy-load.js.map +1 -1
  17. package/esm/components/lazy-load.spec.js +57 -50
  18. package/esm/components/lazy-load.spec.js.map +1 -1
  19. package/esm/components/link-to-route.d.ts +2 -0
  20. package/esm/components/link-to-route.d.ts.map +1 -1
  21. package/esm/components/link-to-route.js +3 -2
  22. package/esm/components/link-to-route.js.map +1 -1
  23. package/esm/components/link-to-route.spec.js +13 -9
  24. package/esm/components/link-to-route.spec.js.map +1 -1
  25. package/esm/components/nested-route-link.d.ts +62 -0
  26. package/esm/components/nested-route-link.d.ts.map +1 -0
  27. package/esm/components/nested-route-link.js +66 -0
  28. package/esm/components/nested-route-link.js.map +1 -0
  29. package/esm/components/nested-route-link.spec.d.ts +2 -0
  30. package/esm/components/nested-route-link.spec.d.ts.map +1 -0
  31. package/esm/components/nested-route-link.spec.js +179 -0
  32. package/esm/components/nested-route-link.spec.js.map +1 -0
  33. package/esm/components/nested-route-types.d.ts +37 -0
  34. package/esm/components/nested-route-types.d.ts.map +1 -0
  35. package/esm/components/nested-route-types.js +2 -0
  36. package/esm/components/nested-route-types.js.map +1 -0
  37. package/esm/components/nested-router.d.ts +103 -0
  38. package/esm/components/nested-router.d.ts.map +1 -0
  39. package/esm/components/nested-router.js +178 -0
  40. package/esm/components/nested-router.js.map +1 -0
  41. package/esm/components/nested-router.spec.d.ts +2 -0
  42. package/esm/components/nested-router.spec.d.ts.map +1 -0
  43. package/esm/components/nested-router.spec.js +659 -0
  44. package/esm/components/nested-router.spec.js.map +1 -0
  45. package/esm/components/route-link.d.ts +4 -0
  46. package/esm/components/route-link.d.ts.map +1 -1
  47. package/esm/components/route-link.js +9 -10
  48. package/esm/components/route-link.js.map +1 -1
  49. package/esm/components/route-link.spec.js +16 -12
  50. package/esm/components/route-link.spec.js.map +1 -1
  51. package/esm/components/router.d.ts +20 -2
  52. package/esm/components/router.d.ts.map +1 -1
  53. package/esm/components/router.js +3 -0
  54. package/esm/components/router.js.map +1 -1
  55. package/esm/components/router.spec.js +75 -74
  56. package/esm/components/router.spec.js.map +1 -1
  57. package/esm/css-generator.d.ts +50 -0
  58. package/esm/css-generator.d.ts.map +1 -0
  59. package/esm/css-generator.js +107 -0
  60. package/esm/css-generator.js.map +1 -0
  61. package/esm/css-generator.spec.d.ts +2 -0
  62. package/esm/css-generator.spec.d.ts.map +1 -0
  63. package/esm/css-generator.spec.js +162 -0
  64. package/esm/css-generator.spec.js.map +1 -0
  65. package/esm/index.d.ts +2 -0
  66. package/esm/index.d.ts.map +1 -1
  67. package/esm/index.js +2 -0
  68. package/esm/index.js.map +1 -1
  69. package/esm/initialize.d.ts +11 -0
  70. package/esm/initialize.d.ts.map +1 -1
  71. package/esm/initialize.js +5 -0
  72. package/esm/initialize.js.map +1 -1
  73. package/esm/jsx.d.ts +83 -2
  74. package/esm/jsx.d.ts.map +1 -1
  75. package/esm/models/children-list.d.ts +5 -1
  76. package/esm/models/children-list.d.ts.map +1 -1
  77. package/esm/models/css-object.d.ts +33 -0
  78. package/esm/models/css-object.d.ts.map +1 -0
  79. package/esm/models/css-object.js +2 -0
  80. package/esm/models/css-object.js.map +1 -0
  81. package/esm/models/index.d.ts +1 -0
  82. package/esm/models/index.d.ts.map +1 -1
  83. package/esm/models/index.js +1 -0
  84. package/esm/models/index.js.map +1 -1
  85. package/esm/models/partial-element.d.ts +12 -2
  86. package/esm/models/partial-element.d.ts.map +1 -1
  87. package/esm/models/render-options.d.ts +89 -3
  88. package/esm/models/render-options.d.ts.map +1 -1
  89. package/esm/models/selection-state.d.ts +4 -0
  90. package/esm/models/selection-state.d.ts.map +1 -1
  91. package/esm/services/location-service.d.ts +11 -0
  92. package/esm/services/location-service.d.ts.map +1 -1
  93. package/esm/services/location-service.js +11 -0
  94. package/esm/services/location-service.js.map +1 -1
  95. package/esm/services/resource-manager.d.ts +24 -0
  96. package/esm/services/resource-manager.d.ts.map +1 -1
  97. package/esm/services/resource-manager.js +30 -0
  98. package/esm/services/resource-manager.js.map +1 -1
  99. package/esm/services/resource-manager.spec.js +93 -0
  100. package/esm/services/resource-manager.spec.js.map +1 -1
  101. package/esm/services/screen-service.d.ts +81 -4
  102. package/esm/services/screen-service.d.ts.map +1 -1
  103. package/esm/services/screen-service.js +75 -4
  104. package/esm/services/screen-service.js.map +1 -1
  105. package/esm/services/screen-service.spec.js +91 -7
  106. package/esm/services/screen-service.spec.js.map +1 -1
  107. package/esm/shade-component.d.ts +17 -4
  108. package/esm/shade-component.d.ts.map +1 -1
  109. package/esm/shade-component.js +67 -5
  110. package/esm/shade-component.js.map +1 -1
  111. package/esm/shade-host-props-ref.integration.spec.d.ts +2 -0
  112. package/esm/shade-host-props-ref.integration.spec.d.ts.map +1 -0
  113. package/esm/shade-host-props-ref.integration.spec.js +381 -0
  114. package/esm/shade-host-props-ref.integration.spec.js.map +1 -0
  115. package/esm/shade-resources.integration.spec.js +208 -39
  116. package/esm/shade-resources.integration.spec.js.map +1 -1
  117. package/esm/shade.d.ts +34 -15
  118. package/esm/shade.d.ts.map +1 -1
  119. package/esm/shade.js +180 -33
  120. package/esm/shade.js.map +1 -1
  121. package/esm/shade.spec.d.ts +2 -0
  122. package/esm/shade.spec.d.ts.map +1 -0
  123. package/esm/shade.spec.js +198 -0
  124. package/esm/shade.spec.js.map +1 -0
  125. package/esm/shades.integration.spec.js +135 -72
  126. package/esm/shades.integration.spec.js.map +1 -1
  127. package/esm/style-manager.d.ts +65 -0
  128. package/esm/style-manager.d.ts.map +1 -0
  129. package/esm/style-manager.js +95 -0
  130. package/esm/style-manager.js.map +1 -0
  131. package/esm/style-manager.spec.d.ts +2 -0
  132. package/esm/style-manager.spec.d.ts.map +1 -0
  133. package/esm/style-manager.spec.js +179 -0
  134. package/esm/style-manager.spec.js.map +1 -0
  135. package/esm/styled-element.spec.d.ts +2 -0
  136. package/esm/styled-element.spec.d.ts.map +1 -0
  137. package/esm/styled-element.spec.js +86 -0
  138. package/esm/styled-element.spec.js.map +1 -0
  139. package/esm/styled-shade.spec.d.ts +2 -0
  140. package/esm/styled-shade.spec.d.ts.map +1 -0
  141. package/esm/styled-shade.spec.js +66 -0
  142. package/esm/styled-shade.spec.js.map +1 -0
  143. package/esm/svg-types.d.ts +389 -0
  144. package/esm/svg-types.d.ts.map +1 -0
  145. package/esm/svg-types.js +9 -0
  146. package/esm/svg-types.js.map +1 -0
  147. package/esm/svg.d.ts +15 -0
  148. package/esm/svg.d.ts.map +1 -0
  149. package/esm/svg.js +76 -0
  150. package/esm/svg.js.map +1 -0
  151. package/esm/svg.spec.d.ts +2 -0
  152. package/esm/svg.spec.d.ts.map +1 -0
  153. package/esm/svg.spec.js +80 -0
  154. package/esm/svg.spec.js.map +1 -0
  155. package/esm/vnode.d.ts +103 -0
  156. package/esm/vnode.d.ts.map +1 -0
  157. package/esm/vnode.integration.spec.d.ts +2 -0
  158. package/esm/vnode.integration.spec.d.ts.map +1 -0
  159. package/esm/vnode.integration.spec.js +494 -0
  160. package/esm/vnode.integration.spec.js.map +1 -0
  161. package/esm/vnode.js +453 -0
  162. package/esm/vnode.js.map +1 -0
  163. package/esm/vnode.spec.d.ts +2 -0
  164. package/esm/vnode.spec.d.ts.map +1 -0
  165. package/esm/vnode.spec.js +473 -0
  166. package/esm/vnode.spec.js.map +1 -0
  167. package/package.json +3 -3
  168. package/src/compile-route.spec.ts +39 -0
  169. package/src/component-factory.spec.tsx +18 -5
  170. package/src/components/index.ts +4 -1
  171. package/src/components/lazy-load.spec.tsx +82 -75
  172. package/src/components/lazy-load.tsx +49 -27
  173. package/src/components/link-to-route.spec.tsx +25 -21
  174. package/src/components/link-to-route.tsx +4 -2
  175. package/src/components/nested-route-link.spec.tsx +303 -0
  176. package/src/components/nested-route-link.tsx +100 -0
  177. package/src/components/nested-route-types.ts +42 -0
  178. package/src/components/nested-router.spec.tsx +817 -0
  179. package/src/components/nested-router.tsx +256 -0
  180. package/src/components/route-link.spec.tsx +22 -18
  181. package/src/components/route-link.tsx +10 -10
  182. package/src/components/router.spec.tsx +109 -108
  183. package/src/components/router.tsx +15 -2
  184. package/src/css-generator.spec.ts +183 -0
  185. package/src/css-generator.ts +117 -0
  186. package/src/index.ts +2 -0
  187. package/src/initialize.ts +12 -0
  188. package/src/jsx.ts +129 -2
  189. package/src/models/children-list.ts +7 -1
  190. package/src/models/css-object.ts +34 -0
  191. package/src/models/index.ts +1 -0
  192. package/src/models/partial-element.ts +13 -2
  193. package/src/models/render-options.ts +90 -3
  194. package/src/models/selection-state.ts +4 -0
  195. package/src/services/location-service.tsx +11 -0
  196. package/src/services/resource-manager.spec.ts +116 -0
  197. package/src/services/resource-manager.ts +30 -0
  198. package/src/services/screen-service.spec.ts +109 -7
  199. package/src/services/screen-service.ts +81 -4
  200. package/src/shade-component.ts +72 -6
  201. package/src/shade-host-props-ref.integration.spec.tsx +460 -0
  202. package/src/shade-resources.integration.spec.tsx +276 -52
  203. package/src/shade.spec.tsx +239 -0
  204. package/src/shade.ts +211 -56
  205. package/src/shades.integration.spec.tsx +154 -80
  206. package/src/style-manager.spec.ts +229 -0
  207. package/src/style-manager.ts +104 -0
  208. package/src/styled-element.spec.tsx +117 -0
  209. package/src/styled-shade.spec.ts +86 -0
  210. package/src/svg-types.ts +437 -0
  211. package/src/svg.spec.ts +89 -0
  212. package/src/svg.ts +78 -0
  213. package/src/vnode.integration.spec.tsx +657 -0
  214. package/src/vnode.spec.ts +579 -0
  215. package/src/vnode.ts +508 -0
@@ -0,0 +1,437 @@
1
+ /**
2
+ * SVG element attribute types for JSX support.
3
+ *
4
+ * Unlike HTML elements where JSX props map to DOM properties, SVG elements
5
+ * use XML attributes set via `setAttribute`. These types describe the
6
+ * attribute-based API rather than the DOM property interfaces.
7
+ */
8
+
9
+ import type { RefObject } from './models/render-options.js'
10
+
11
+ /**
12
+ * Common event handlers available on SVG elements.
13
+ */
14
+ export type SvgEventHandlers = {
15
+ onclick?: (ev: MouseEvent) => void
16
+ ondblclick?: (ev: MouseEvent) => void
17
+ onmousedown?: (ev: MouseEvent) => void
18
+ onmouseup?: (ev: MouseEvent) => void
19
+ onmousemove?: (ev: MouseEvent) => void
20
+ onmouseenter?: (ev: MouseEvent) => void
21
+ onmouseleave?: (ev: MouseEvent) => void
22
+ onmouseover?: (ev: MouseEvent) => void
23
+ onmouseout?: (ev: MouseEvent) => void
24
+ onfocus?: (ev: FocusEvent) => void
25
+ onblur?: (ev: FocusEvent) => void
26
+ onkeydown?: (ev: KeyboardEvent) => void
27
+ onkeyup?: (ev: KeyboardEvent) => void
28
+ ontouchstart?: (ev: TouchEvent) => void
29
+ ontouchmove?: (ev: TouchEvent) => void
30
+ ontouchend?: (ev: TouchEvent) => void
31
+ }
32
+
33
+ /**
34
+ * SVG presentation attributes shared by most SVG elements.
35
+ * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation
36
+ */
37
+ export type SvgPresentationAttributes = {
38
+ 'clip-path'?: string
39
+ 'clip-rule'?: 'nonzero' | 'evenodd'
40
+ color?: string
41
+ cursor?: string
42
+ display?: string
43
+ fill?: string
44
+ 'fill-opacity'?: string | number
45
+ 'fill-rule'?: 'nonzero' | 'evenodd'
46
+ filter?: string
47
+ 'flood-color'?: string
48
+ 'flood-opacity'?: string | number
49
+ 'font-family'?: string
50
+ 'font-size'?: string | number
51
+ 'font-style'?: 'normal' | 'italic' | 'oblique'
52
+ 'font-weight'?: string | number
53
+ 'letter-spacing'?: string | number
54
+ 'lighting-color'?: string
55
+ marker?: string
56
+ 'marker-end'?: string
57
+ 'marker-mid'?: string
58
+ 'marker-start'?: string
59
+ mask?: string
60
+ opacity?: string | number
61
+ overflow?: string
62
+ 'pointer-events'?: string
63
+ 'shape-rendering'?: 'auto' | 'optimizeSpeed' | 'crispEdges' | 'geometricPrecision'
64
+ 'stop-color'?: string
65
+ 'stop-opacity'?: string | number
66
+ stroke?: string
67
+ 'stroke-dasharray'?: string
68
+ 'stroke-dashoffset'?: string | number
69
+ 'stroke-linecap'?: 'butt' | 'round' | 'square'
70
+ 'stroke-linejoin'?: 'arcs' | 'bevel' | 'miter' | 'miter-clip' | 'round'
71
+ 'stroke-miterlimit'?: string | number
72
+ 'stroke-opacity'?: string | number
73
+ 'stroke-width'?: string | number
74
+ 'text-anchor'?: 'start' | 'middle' | 'end'
75
+ 'text-decoration'?: string
76
+ 'dominant-baseline'?: string
77
+ 'alignment-baseline'?: string
78
+ transform?: string
79
+ 'transform-origin'?: string
80
+ visibility?: 'visible' | 'hidden' | 'collapse'
81
+ 'word-spacing'?: string | number
82
+ }
83
+
84
+ /**
85
+ * Core attributes available on all SVG elements.
86
+ */
87
+ export type SvgCoreAttributes = {
88
+ id?: string
89
+ className?: string
90
+ style?: Partial<CSSStyleDeclaration>
91
+ tabIndex?: number
92
+ ref?: RefObject<Element>
93
+ } & SvgPresentationAttributes &
94
+ SvgEventHandlers
95
+
96
+ // ---------------------------------------------------------------------------
97
+ // Element-specific attribute types
98
+ // ---------------------------------------------------------------------------
99
+
100
+ /** Attributes for the `<svg>` element. */
101
+ export type SvgSvgAttributes = SvgCoreAttributes & {
102
+ viewBox?: string
103
+ width?: string | number
104
+ height?: string | number
105
+ xmlns?: string
106
+ preserveAspectRatio?: string
107
+ x?: string | number
108
+ y?: string | number
109
+ }
110
+
111
+ /** Attributes for the `<g>` element. */
112
+ export type SvgGAttributes = SvgCoreAttributes
113
+
114
+ /** Attributes for the `<defs>` element. */
115
+ export type SvgDefsAttributes = SvgCoreAttributes
116
+
117
+ /** Attributes for the `<symbol>` element. */
118
+ export type SvgSymbolAttributes = SvgCoreAttributes & {
119
+ viewBox?: string
120
+ preserveAspectRatio?: string
121
+ x?: string | number
122
+ y?: string | number
123
+ width?: string | number
124
+ height?: string | number
125
+ refX?: string | number
126
+ refY?: string | number
127
+ }
128
+
129
+ /** Attributes for the `<use>` element. */
130
+ export type SvgUseAttributes = SvgCoreAttributes & {
131
+ href?: string
132
+ x?: string | number
133
+ y?: string | number
134
+ width?: string | number
135
+ height?: string | number
136
+ }
137
+
138
+ /** Attributes for the `<path>` element. */
139
+ export type SvgPathAttributes = SvgCoreAttributes & {
140
+ d: string
141
+ pathLength?: number
142
+ }
143
+
144
+ /** Attributes for the `<rect>` element. */
145
+ export type SvgRectAttributes = SvgCoreAttributes & {
146
+ x?: string | number
147
+ y?: string | number
148
+ width?: string | number
149
+ height?: string | number
150
+ rx?: string | number
151
+ ry?: string | number
152
+ pathLength?: number
153
+ }
154
+
155
+ /** Attributes for the `<circle>` element. */
156
+ export type SvgCircleAttributes = SvgCoreAttributes & {
157
+ cx?: string | number
158
+ cy?: string | number
159
+ r?: string | number
160
+ pathLength?: number
161
+ }
162
+
163
+ /** Attributes for the `<ellipse>` element. */
164
+ export type SvgEllipseAttributes = SvgCoreAttributes & {
165
+ cx?: string | number
166
+ cy?: string | number
167
+ rx?: string | number
168
+ ry?: string | number
169
+ pathLength?: number
170
+ }
171
+
172
+ /** Attributes for the `<line>` element. */
173
+ export type SvgLineAttributes = SvgCoreAttributes & {
174
+ x1?: string | number
175
+ y1?: string | number
176
+ x2?: string | number
177
+ y2?: string | number
178
+ pathLength?: number
179
+ }
180
+
181
+ /** Attributes for the `<polyline>` element. */
182
+ export type SvgPolylineAttributes = SvgCoreAttributes & {
183
+ points?: string
184
+ pathLength?: number
185
+ }
186
+
187
+ /** Attributes for the `<polygon>` element. */
188
+ export type SvgPolygonAttributes = SvgCoreAttributes & {
189
+ points?: string
190
+ pathLength?: number
191
+ }
192
+
193
+ /** Attributes for the `<text>` element. */
194
+ export type SvgTextAttributes = SvgCoreAttributes & {
195
+ x?: string | number
196
+ y?: string | number
197
+ dx?: string | number
198
+ dy?: string | number
199
+ rotate?: string
200
+ textLength?: string | number
201
+ lengthAdjust?: 'spacing' | 'spacingAndGlyphs'
202
+ }
203
+
204
+ /** Attributes for the `<tspan>` element. */
205
+ export type SvgTspanAttributes = SvgCoreAttributes & {
206
+ x?: string | number
207
+ y?: string | number
208
+ dx?: string | number
209
+ dy?: string | number
210
+ rotate?: string
211
+ textLength?: string | number
212
+ lengthAdjust?: 'spacing' | 'spacingAndGlyphs'
213
+ }
214
+
215
+ /** Attributes for the `<textPath>` element. */
216
+ export type SvgTextPathAttributes = SvgCoreAttributes & {
217
+ href?: string
218
+ method?: 'align' | 'stretch'
219
+ spacing?: 'auto' | 'exact'
220
+ startOffset?: string | number
221
+ textLength?: string | number
222
+ lengthAdjust?: 'spacing' | 'spacingAndGlyphs'
223
+ }
224
+
225
+ /** Attributes for the `<clipPath>` element. */
226
+ export type SvgClipPathAttributes = SvgCoreAttributes & {
227
+ clipPathUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
228
+ }
229
+
230
+ /** Attributes for the `<mask>` element. */
231
+ export type SvgMaskAttributes = SvgCoreAttributes & {
232
+ maskUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
233
+ maskContentUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
234
+ x?: string | number
235
+ y?: string | number
236
+ width?: string | number
237
+ height?: string | number
238
+ }
239
+
240
+ /** Attributes for the `<linearGradient>` element. */
241
+ export type SvgLinearGradientAttributes = SvgCoreAttributes & {
242
+ x1?: string | number
243
+ y1?: string | number
244
+ x2?: string | number
245
+ y2?: string | number
246
+ gradientUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
247
+ gradientTransform?: string
248
+ spreadMethod?: 'pad' | 'reflect' | 'repeat'
249
+ href?: string
250
+ }
251
+
252
+ /** Attributes for the `<radialGradient>` element. */
253
+ export type SvgRadialGradientAttributes = SvgCoreAttributes & {
254
+ cx?: string | number
255
+ cy?: string | number
256
+ r?: string | number
257
+ fx?: string | number
258
+ fy?: string | number
259
+ fr?: string | number
260
+ gradientUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
261
+ gradientTransform?: string
262
+ spreadMethod?: 'pad' | 'reflect' | 'repeat'
263
+ href?: string
264
+ }
265
+
266
+ /** Attributes for the `<stop>` element. */
267
+ export type SvgStopAttributes = SvgCoreAttributes & {
268
+ offset?: string | number
269
+ 'stop-color'?: string
270
+ 'stop-opacity'?: string | number
271
+ }
272
+
273
+ /** Attributes for the `<pattern>` element. */
274
+ export type SvgPatternAttributes = SvgCoreAttributes & {
275
+ x?: string | number
276
+ y?: string | number
277
+ width?: string | number
278
+ height?: string | number
279
+ patternUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
280
+ patternContentUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
281
+ patternTransform?: string
282
+ viewBox?: string
283
+ preserveAspectRatio?: string
284
+ href?: string
285
+ }
286
+
287
+ /** Attributes for the `<marker>` element. */
288
+ export type SvgMarkerAttributes = SvgCoreAttributes & {
289
+ viewBox?: string
290
+ preserveAspectRatio?: string
291
+ refX?: string | number
292
+ refY?: string | number
293
+ markerUnits?: 'strokeWidth' | 'userSpaceOnUse'
294
+ markerWidth?: string | number
295
+ markerHeight?: string | number
296
+ orient?: string
297
+ }
298
+
299
+ /** Attributes for the `<filter>` element. */
300
+ export type SvgFilterAttributes = SvgCoreAttributes & {
301
+ x?: string | number
302
+ y?: string | number
303
+ width?: string | number
304
+ height?: string | number
305
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
306
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox'
307
+ }
308
+
309
+ /** Common attributes for SVG filter primitive elements. */
310
+ type SvgFilterPrimitiveAttributes = SvgCoreAttributes & {
311
+ x?: string | number
312
+ y?: string | number
313
+ width?: string | number
314
+ height?: string | number
315
+ result?: string
316
+ }
317
+
318
+ /** Attributes for the `<feGaussianBlur>` element. */
319
+ export type SvgFeGaussianBlurAttributes = SvgFilterPrimitiveAttributes & {
320
+ in?: string
321
+ stdDeviation?: string | number
322
+ edgeMode?: 'duplicate' | 'wrap' | 'none'
323
+ }
324
+
325
+ /** Attributes for the `<feBlend>` element. */
326
+ export type SvgFeBlendAttributes = SvgFilterPrimitiveAttributes & {
327
+ in?: string
328
+ in2?: string
329
+ mode?: 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten'
330
+ }
331
+
332
+ /** Attributes for the `<feColorMatrix>` element. */
333
+ export type SvgFeColorMatrixAttributes = SvgFilterPrimitiveAttributes & {
334
+ in?: string
335
+ type?: 'matrix' | 'saturate' | 'hueRotate' | 'luminanceToAlpha'
336
+ values?: string
337
+ }
338
+
339
+ /** Attributes for the `<feOffset>` element. */
340
+ export type SvgFeOffsetAttributes = SvgFilterPrimitiveAttributes & {
341
+ in?: string
342
+ dx?: string | number
343
+ dy?: string | number
344
+ }
345
+
346
+ /** Attributes for the `<feFlood>` element. */
347
+ export type SvgFeFloodAttributes = SvgFilterPrimitiveAttributes & {
348
+ 'flood-color'?: string
349
+ 'flood-opacity'?: string | number
350
+ }
351
+
352
+ /** Attributes for the `<feMerge>` element. */
353
+ export type SvgFeMergeAttributes = SvgFilterPrimitiveAttributes
354
+
355
+ /** Attributes for the `<feMergeNode>` element. */
356
+ export type SvgFeMergeNodeAttributes = SvgCoreAttributes & {
357
+ in?: string
358
+ }
359
+
360
+ /** Attributes for the `<feComposite>` element. */
361
+ export type SvgFeCompositeAttributes = SvgFilterPrimitiveAttributes & {
362
+ in?: string
363
+ in2?: string
364
+ operator?: 'over' | 'in' | 'out' | 'atop' | 'xor' | 'lighter' | 'arithmetic'
365
+ k1?: number
366
+ k2?: number
367
+ k3?: number
368
+ k4?: number
369
+ }
370
+
371
+ /** Attributes for the `<image>` element (SVG). */
372
+ export type SvgImageAttributes = SvgCoreAttributes & {
373
+ href?: string
374
+ x?: string | number
375
+ y?: string | number
376
+ width?: string | number
377
+ height?: string | number
378
+ preserveAspectRatio?: string
379
+ crossorigin?: 'anonymous' | 'use-credentials'
380
+ }
381
+
382
+ /** Attributes for the `<foreignObject>` element. */
383
+ export type SvgForeignObjectAttributes = SvgCoreAttributes & {
384
+ x?: string | number
385
+ y?: string | number
386
+ width?: string | number
387
+ height?: string | number
388
+ }
389
+
390
+ /** Common attributes for SVG animation elements. */
391
+ type SvgAnimationAttributes = SvgCoreAttributes & {
392
+ attributeName?: string
393
+ begin?: string
394
+ dur?: string
395
+ end?: string
396
+ repeatCount?: string | number
397
+ repeatDur?: string
398
+ fill?: 'freeze' | 'remove'
399
+ from?: string
400
+ to?: string
401
+ by?: string
402
+ values?: string
403
+ keyTimes?: string
404
+ keySplines?: string
405
+ calcMode?: 'discrete' | 'linear' | 'paced' | 'spline'
406
+ }
407
+
408
+ /** Attributes for the `<animate>` element. */
409
+ export type SvgAnimateAttributes = SvgAnimationAttributes
410
+
411
+ /** Attributes for the `<animateMotion>` element. */
412
+ export type SvgAnimateMotionAttributes = SvgAnimationAttributes & {
413
+ path?: string
414
+ rotate?: string
415
+ }
416
+
417
+ /** Attributes for the `<animateTransform>` element. */
418
+ export type SvgAnimateTransformAttributes = SvgAnimationAttributes & {
419
+ type?: 'translate' | 'scale' | 'rotate' | 'skewX' | 'skewY'
420
+ }
421
+
422
+ /** Attributes for the `<set>` element. */
423
+ export type SvgSetAttributes = SvgCoreAttributes & {
424
+ attributeName?: string
425
+ to?: string
426
+ begin?: string
427
+ dur?: string
428
+ end?: string
429
+ repeatCount?: string | number
430
+ fill?: 'freeze' | 'remove'
431
+ }
432
+
433
+ /** Attributes for the `<title>` element (SVG). */
434
+ export type SvgTitleAttributes = SvgCoreAttributes
435
+
436
+ /** Attributes for the `<desc>` element. */
437
+ export type SvgDescAttributes = SvgCoreAttributes
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { isSvgTag, SVG_NS, SVG_TAGS } from './svg.js'
3
+
4
+ describe('svg', () => {
5
+ describe('SVG_NS', () => {
6
+ it('should be the standard SVG namespace URI', () => {
7
+ expect(SVG_NS).toBe('http://www.w3.org/2000/svg')
8
+ })
9
+ })
10
+
11
+ describe('SVG_TAGS', () => {
12
+ it('should contain core SVG element tags', () => {
13
+ const coreTags = ['svg', 'g', 'path', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon']
14
+ for (const tag of coreTags) {
15
+ expect(SVG_TAGS.has(tag)).toBe(true)
16
+ }
17
+ })
18
+
19
+ it('should contain text-related SVG tags', () => {
20
+ expect(SVG_TAGS.has('text')).toBe(true)
21
+ expect(SVG_TAGS.has('tspan')).toBe(true)
22
+ expect(SVG_TAGS.has('textPath')).toBe(true)
23
+ })
24
+
25
+ it('should contain gradient and pattern tags', () => {
26
+ expect(SVG_TAGS.has('linearGradient')).toBe(true)
27
+ expect(SVG_TAGS.has('radialGradient')).toBe(true)
28
+ expect(SVG_TAGS.has('stop')).toBe(true)
29
+ expect(SVG_TAGS.has('pattern')).toBe(true)
30
+ })
31
+
32
+ it('should contain filter primitive tags', () => {
33
+ const filterTags = [
34
+ 'filter',
35
+ 'feBlend',
36
+ 'feColorMatrix',
37
+ 'feGaussianBlur',
38
+ 'feOffset',
39
+ 'feFlood',
40
+ 'feMerge',
41
+ 'feMergeNode',
42
+ 'feComposite',
43
+ ]
44
+ for (const tag of filterTags) {
45
+ expect(SVG_TAGS.has(tag)).toBe(true)
46
+ }
47
+ })
48
+
49
+ it('should contain animation tags', () => {
50
+ expect(SVG_TAGS.has('animate')).toBe(true)
51
+ expect(SVG_TAGS.has('animateMotion')).toBe(true)
52
+ expect(SVG_TAGS.has('animateTransform')).toBe(true)
53
+ expect(SVG_TAGS.has('set')).toBe(true)
54
+ })
55
+
56
+ it('should not contain HTML element tags', () => {
57
+ const htmlTags = ['div', 'span', 'p', 'button', 'input', 'form', 'table', 'a', 'img']
58
+ for (const tag of htmlTags) {
59
+ expect(SVG_TAGS.has(tag)).toBe(false)
60
+ }
61
+ })
62
+ })
63
+
64
+ describe('isSvgTag', () => {
65
+ it('should return true for known SVG tags', () => {
66
+ expect(isSvgTag('svg')).toBe(true)
67
+ expect(isSvgTag('path')).toBe(true)
68
+ expect(isSvgTag('circle')).toBe(true)
69
+ expect(isSvgTag('g')).toBe(true)
70
+ expect(isSvgTag('feGaussianBlur')).toBe(true)
71
+ expect(isSvgTag('linearGradient')).toBe(true)
72
+ expect(isSvgTag('clipPath')).toBe(true)
73
+ expect(isSvgTag('foreignObject')).toBe(true)
74
+ })
75
+
76
+ it('should return false for HTML tags', () => {
77
+ expect(isSvgTag('div')).toBe(false)
78
+ expect(isSvgTag('span')).toBe(false)
79
+ expect(isSvgTag('button')).toBe(false)
80
+ expect(isSvgTag('input')).toBe(false)
81
+ })
82
+
83
+ it('should return false for unknown tags', () => {
84
+ expect(isSvgTag('my-component')).toBe(false)
85
+ expect(isSvgTag('')).toBe(false)
86
+ expect(isSvgTag('SVG')).toBe(false)
87
+ })
88
+ })
89
+ })
package/src/svg.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * SVG namespace and tag detection helpers.
3
+ */
4
+
5
+ export const SVG_NS = 'http://www.w3.org/2000/svg'
6
+
7
+ /**
8
+ * Set of known SVG element tag names.
9
+ * Used to determine whether to create elements with `createElementNS`
10
+ * and to apply attributes via `setAttribute` instead of property assignment.
11
+ */
12
+ export const SVG_TAGS: ReadonlySet<string> = new Set([
13
+ // Root
14
+ 'svg',
15
+ // Container / structural
16
+ 'g',
17
+ 'defs',
18
+ 'symbol',
19
+ 'use',
20
+ 'foreignObject',
21
+ // Shape elements
22
+ 'path',
23
+ 'rect',
24
+ 'circle',
25
+ 'ellipse',
26
+ 'line',
27
+ 'polyline',
28
+ 'polygon',
29
+ // Text
30
+ 'text',
31
+ 'tspan',
32
+ 'textPath',
33
+ // Gradient / pattern
34
+ 'linearGradient',
35
+ 'radialGradient',
36
+ 'stop',
37
+ 'pattern',
38
+ // Clipping / masking
39
+ 'clipPath',
40
+ 'mask',
41
+ // Marker
42
+ 'marker',
43
+ // Filter
44
+ 'filter',
45
+ 'feBlend',
46
+ 'feColorMatrix',
47
+ 'feComponentTransfer',
48
+ 'feComposite',
49
+ 'feConvolveMatrix',
50
+ 'feDiffuseLighting',
51
+ 'feDisplacementMap',
52
+ 'feFlood',
53
+ 'feGaussianBlur',
54
+ 'feImage',
55
+ 'feMerge',
56
+ 'feMergeNode',
57
+ 'feMorphology',
58
+ 'feOffset',
59
+ 'feSpecularLighting',
60
+ 'feTile',
61
+ 'feTurbulence',
62
+ // Animation
63
+ 'animate',
64
+ 'animateMotion',
65
+ 'animateTransform',
66
+ 'set',
67
+ // Descriptive
68
+ 'title',
69
+ 'desc',
70
+ 'metadata',
71
+ // Other
72
+ 'image',
73
+ ])
74
+
75
+ /**
76
+ * Returns true if the given tag name is a known SVG element.
77
+ */
78
+ export const isSvgTag = (tag: string): boolean => SVG_TAGS.has(tag)