@pithyjs/ui-kit 0.1.0-beta.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 (417) hide show
  1. package/LICENSE +21 -0
  2. package/dist/animation/animate-in.d.ts +35 -0
  3. package/dist/animation/animate-in.d.ts.map +1 -0
  4. package/dist/animation/animate-in.js +71 -0
  5. package/dist/animation/animate-in.js.map +1 -0
  6. package/dist/atoms/actions/_icon-control.scss +53 -0
  7. package/dist/atoms/actions/button/Button.d.ts +93 -0
  8. package/dist/atoms/actions/button/Button.d.ts.map +1 -0
  9. package/dist/atoms/actions/button/Button.js +332 -0
  10. package/dist/atoms/actions/button/Button.js.map +1 -0
  11. package/dist/atoms/actions/button/button.scss +342 -0
  12. package/dist/atoms/actions/icon-button/IconButton.d.ts +47 -0
  13. package/dist/atoms/actions/icon-button/IconButton.d.ts.map +1 -0
  14. package/dist/atoms/actions/icon-button/IconButton.js +81 -0
  15. package/dist/atoms/actions/icon-button/IconButton.js.map +1 -0
  16. package/dist/atoms/actions/icon-button/icon-button.scss +20 -0
  17. package/dist/atoms/actions/icon-group/IconGroup.d.ts +60 -0
  18. package/dist/atoms/actions/icon-group/IconGroup.d.ts.map +1 -0
  19. package/dist/atoms/actions/icon-group/IconGroup.js +191 -0
  20. package/dist/atoms/actions/icon-group/IconGroup.js.map +1 -0
  21. package/dist/atoms/actions/icon-group/icon-group.scss +36 -0
  22. package/dist/atoms/actions/segmented-control/SegmentedControl.d.ts +49 -0
  23. package/dist/atoms/actions/segmented-control/SegmentedControl.d.ts.map +1 -0
  24. package/dist/atoms/actions/segmented-control/SegmentedControl.js +107 -0
  25. package/dist/atoms/actions/segmented-control/SegmentedControl.js.map +1 -0
  26. package/dist/atoms/actions/segmented-control/segmented-control.scss +90 -0
  27. package/dist/atoms/content/_mixins.scss +79 -0
  28. package/dist/atoms/content/action-tile/ActionTile.d.ts +27 -0
  29. package/dist/atoms/content/action-tile/ActionTile.d.ts.map +1 -0
  30. package/dist/atoms/content/action-tile/ActionTile.js +98 -0
  31. package/dist/atoms/content/action-tile/ActionTile.js.map +1 -0
  32. package/dist/atoms/content/action-tile/action-tile.scss +150 -0
  33. package/dist/atoms/content/badge/Badge.d.ts +57 -0
  34. package/dist/atoms/content/badge/Badge.d.ts.map +1 -0
  35. package/dist/atoms/content/badge/Badge.js +177 -0
  36. package/dist/atoms/content/badge/Badge.js.map +1 -0
  37. package/dist/atoms/content/badge/badge.scss +198 -0
  38. package/dist/atoms/content/heading/Heading.d.ts +53 -0
  39. package/dist/atoms/content/heading/Heading.d.ts.map +1 -0
  40. package/dist/atoms/content/heading/Heading.js +142 -0
  41. package/dist/atoms/content/heading/Heading.js.map +1 -0
  42. package/dist/atoms/content/heading/heading.scss +43 -0
  43. package/dist/atoms/content/icon/Icon.d.ts +68 -0
  44. package/dist/atoms/content/icon/Icon.d.ts.map +1 -0
  45. package/dist/atoms/content/icon/Icon.js +137 -0
  46. package/dist/atoms/content/icon/Icon.js.map +1 -0
  47. package/dist/atoms/content/icon/icon.scss +66 -0
  48. package/dist/atoms/content/icon/resolveIconSvg.d.ts +21 -0
  49. package/dist/atoms/content/icon/resolveIconSvg.d.ts.map +1 -0
  50. package/dist/atoms/content/icon/resolveIconSvg.js +73 -0
  51. package/dist/atoms/content/icon/resolveIconSvg.js.map +1 -0
  52. package/dist/atoms/content/image/Image.d.ts +81 -0
  53. package/dist/atoms/content/image/Image.d.ts.map +1 -0
  54. package/dist/atoms/content/image/Image.js +293 -0
  55. package/dist/atoms/content/image/Image.js.map +1 -0
  56. package/dist/atoms/content/image/image.scss +77 -0
  57. package/dist/atoms/content/text/Text.d.ts +58 -0
  58. package/dist/atoms/content/text/Text.d.ts.map +1 -0
  59. package/dist/atoms/content/text/Text.js +158 -0
  60. package/dist/atoms/content/text/Text.js.map +1 -0
  61. package/dist/atoms/content/text/text.scss +98 -0
  62. package/dist/atoms/content/tile/Tile.d.ts +66 -0
  63. package/dist/atoms/content/tile/Tile.d.ts.map +1 -0
  64. package/dist/atoms/content/tile/Tile.js +125 -0
  65. package/dist/atoms/content/tile/Tile.js.map +1 -0
  66. package/dist/atoms/content/tile/tile.scss +122 -0
  67. package/dist/atoms/feedback/tooltip/Tooltip.d.ts +44 -0
  68. package/dist/atoms/feedback/tooltip/Tooltip.d.ts.map +1 -0
  69. package/dist/atoms/feedback/tooltip/Tooltip.js +121 -0
  70. package/dist/atoms/feedback/tooltip/Tooltip.js.map +1 -0
  71. package/dist/atoms/feedback/tooltip/tooltip.scss +96 -0
  72. package/dist/atoms/forms/checkbox/Checkbox.d.ts +49 -0
  73. package/dist/atoms/forms/checkbox/Checkbox.d.ts.map +1 -0
  74. package/dist/atoms/forms/checkbox/Checkbox.js +269 -0
  75. package/dist/atoms/forms/checkbox/Checkbox.js.map +1 -0
  76. package/dist/atoms/forms/checkbox/CheckboxGroup.d.ts +50 -0
  77. package/dist/atoms/forms/checkbox/CheckboxGroup.d.ts.map +1 -0
  78. package/dist/atoms/forms/checkbox/CheckboxGroup.js +132 -0
  79. package/dist/atoms/forms/checkbox/CheckboxGroup.js.map +1 -0
  80. package/dist/atoms/forms/checkbox/checkbox.scss +506 -0
  81. package/dist/atoms/forms/file-picker/FilePicker.d.ts +23 -0
  82. package/dist/atoms/forms/file-picker/FilePicker.d.ts.map +1 -0
  83. package/dist/atoms/forms/file-picker/FilePicker.js +103 -0
  84. package/dist/atoms/forms/file-picker/FilePicker.js.map +1 -0
  85. package/dist/atoms/forms/file-picker/file-picker.scss +84 -0
  86. package/dist/atoms/forms/form-field/FormField.d.ts +39 -0
  87. package/dist/atoms/forms/form-field/FormField.d.ts.map +1 -0
  88. package/dist/atoms/forms/form-field/FormField.js +139 -0
  89. package/dist/atoms/forms/form-field/FormField.js.map +1 -0
  90. package/dist/atoms/forms/form-field/form-field.scss +46 -0
  91. package/dist/atoms/forms/input/Input.d.ts +81 -0
  92. package/dist/atoms/forms/input/Input.d.ts.map +1 -0
  93. package/dist/atoms/forms/input/Input.js +417 -0
  94. package/dist/atoms/forms/input/Input.js.map +1 -0
  95. package/dist/atoms/forms/input/input.scss +547 -0
  96. package/dist/atoms/forms/radio/Radio.d.ts +54 -0
  97. package/dist/atoms/forms/radio/Radio.d.ts.map +1 -0
  98. package/dist/atoms/forms/radio/Radio.js +278 -0
  99. package/dist/atoms/forms/radio/Radio.js.map +1 -0
  100. package/dist/atoms/forms/radio/RadioGroup.d.ts +54 -0
  101. package/dist/atoms/forms/radio/RadioGroup.d.ts.map +1 -0
  102. package/dist/atoms/forms/radio/RadioGroup.js +137 -0
  103. package/dist/atoms/forms/radio/RadioGroup.js.map +1 -0
  104. package/dist/atoms/forms/radio/radio.scss +459 -0
  105. package/dist/atoms/forms/select/Select.d.ts +57 -0
  106. package/dist/atoms/forms/select/Select.d.ts.map +1 -0
  107. package/dist/atoms/forms/select/Select.js +457 -0
  108. package/dist/atoms/forms/select/Select.js.map +1 -0
  109. package/dist/atoms/forms/select/select-dropdown.d.ts +49 -0
  110. package/dist/atoms/forms/select/select-dropdown.d.ts.map +1 -0
  111. package/dist/atoms/forms/select/select-dropdown.js +305 -0
  112. package/dist/atoms/forms/select/select-dropdown.js.map +1 -0
  113. package/dist/atoms/forms/select/select-keyboard.d.ts +14 -0
  114. package/dist/atoms/forms/select/select-keyboard.d.ts.map +1 -0
  115. package/dist/atoms/forms/select/select-keyboard.js +182 -0
  116. package/dist/atoms/forms/select/select-keyboard.js.map +1 -0
  117. package/dist/atoms/forms/select/select.scss +630 -0
  118. package/dist/atoms/forms/textarea/Textarea.d.ts +69 -0
  119. package/dist/atoms/forms/textarea/Textarea.d.ts.map +1 -0
  120. package/dist/atoms/forms/textarea/Textarea.js +394 -0
  121. package/dist/atoms/forms/textarea/Textarea.js.map +1 -0
  122. package/dist/atoms/forms/textarea/textarea.scss +486 -0
  123. package/dist/atoms/forms/toggle/Toggle.d.ts +47 -0
  124. package/dist/atoms/forms/toggle/Toggle.d.ts.map +1 -0
  125. package/dist/atoms/forms/toggle/Toggle.js +243 -0
  126. package/dist/atoms/forms/toggle/Toggle.js.map +1 -0
  127. package/dist/atoms/forms/toggle/toggle.scss +561 -0
  128. package/dist/compiler.d.ts +7 -0
  129. package/dist/compiler.d.ts.map +1 -0
  130. package/dist/compiler.js +18 -0
  131. package/dist/compiler.js.map +1 -0
  132. package/dist/icons/index.d.ts +14 -0
  133. package/dist/icons/index.d.ts.map +1 -0
  134. package/dist/icons/index.js +14 -0
  135. package/dist/icons/index.js.map +1 -0
  136. package/dist/icons/registry.d.ts +65 -0
  137. package/dist/icons/registry.d.ts.map +1 -0
  138. package/dist/icons/registry.js +126 -0
  139. package/dist/icons/registry.js.map +1 -0
  140. package/dist/index.d.ts +55 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +64 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/layout/Grid.d.ts +78 -0
  145. package/dist/layout/Grid.d.ts.map +1 -0
  146. package/dist/layout/Grid.js +272 -0
  147. package/dist/layout/Grid.js.map +1 -0
  148. package/dist/layout/GridItem.d.ts +52 -0
  149. package/dist/layout/GridItem.d.ts.map +1 -0
  150. package/dist/layout/GridItem.js +99 -0
  151. package/dist/layout/GridItem.js.map +1 -0
  152. package/dist/layout/PageSection.d.ts +43 -0
  153. package/dist/layout/PageSection.d.ts.map +1 -0
  154. package/dist/layout/PageSection.js +75 -0
  155. package/dist/layout/PageSection.js.map +1 -0
  156. package/dist/layout/SmartContainer.d.ts +66 -0
  157. package/dist/layout/SmartContainer.d.ts.map +1 -0
  158. package/dist/layout/SmartContainer.js +194 -0
  159. package/dist/layout/SmartContainer.js.map +1 -0
  160. package/dist/layout/Stack.d.ts +65 -0
  161. package/dist/layout/Stack.d.ts.map +1 -0
  162. package/dist/layout/Stack.js +114 -0
  163. package/dist/layout/Stack.js.map +1 -0
  164. package/dist/organisms/content/Card.d.ts +93 -0
  165. package/dist/organisms/content/Card.d.ts.map +1 -0
  166. package/dist/organisms/content/Card.js +353 -0
  167. package/dist/organisms/content/Card.js.map +1 -0
  168. package/dist/organisms/content/_card-horizontal.scss +88 -0
  169. package/dist/organisms/content/_card-link.scss +49 -0
  170. package/dist/organisms/content/_card-overlay.scss +91 -0
  171. package/dist/organisms/content/_card-root.scss +99 -0
  172. package/dist/organisms/content/_card-slots.scss +143 -0
  173. package/dist/organisms/content/_card-states.scss +166 -0
  174. package/dist/organisms/content/_card-tokens.scss +22 -0
  175. package/dist/organisms/content/_card-variants.scss +31 -0
  176. package/dist/organisms/content/card.scss +15 -0
  177. package/dist/organisms/feedback/Modal.d.ts +39 -0
  178. package/dist/organisms/feedback/Modal.d.ts.map +1 -0
  179. package/dist/organisms/feedback/Modal.js +120 -0
  180. package/dist/organisms/feedback/Modal.js.map +1 -0
  181. package/dist/organisms/feedback/Popover.d.ts +30 -0
  182. package/dist/organisms/feedback/Popover.d.ts.map +1 -0
  183. package/dist/organisms/feedback/Popover.js +151 -0
  184. package/dist/organisms/feedback/Popover.js.map +1 -0
  185. package/dist/organisms/feedback/modal.scss +66 -0
  186. package/dist/organisms/feedback/popover.scss +27 -0
  187. package/dist/organisms/forms/DynamicForm.d.ts +118 -0
  188. package/dist/organisms/forms/DynamicForm.d.ts.map +1 -0
  189. package/dist/organisms/forms/DynamicForm.js +546 -0
  190. package/dist/organisms/forms/DynamicForm.js.map +1 -0
  191. package/dist/organisms/forms/Form.d.ts +62 -0
  192. package/dist/organisms/forms/Form.d.ts.map +1 -0
  193. package/dist/organisms/forms/Form.js +131 -0
  194. package/dist/organisms/forms/Form.js.map +1 -0
  195. package/dist/organisms/forms/dynamic-form.scss +91 -0
  196. package/dist/organisms/forms/form-helpers.d.ts +21 -0
  197. package/dist/organisms/forms/form-helpers.d.ts.map +1 -0
  198. package/dist/organisms/forms/form-helpers.js +57 -0
  199. package/dist/organisms/forms/form-helpers.js.map +1 -0
  200. package/dist/organisms/forms/form-state.d.ts +66 -0
  201. package/dist/organisms/forms/form-state.d.ts.map +1 -0
  202. package/dist/organisms/forms/form-state.js +156 -0
  203. package/dist/organisms/forms/form-state.js.map +1 -0
  204. package/dist/organisms/forms/form.scss +23 -0
  205. package/dist/organisms/forms/validation.d.ts +32 -0
  206. package/dist/organisms/forms/validation.d.ts.map +1 -0
  207. package/dist/organisms/forms/validation.js +118 -0
  208. package/dist/organisms/forms/validation.js.map +1 -0
  209. package/dist/organisms/navigation/Navbar.d.ts +66 -0
  210. package/dist/organisms/navigation/Navbar.d.ts.map +1 -0
  211. package/dist/organisms/navigation/Navbar.js +881 -0
  212. package/dist/organisms/navigation/Navbar.js.map +1 -0
  213. package/dist/organisms/navigation/_navbar-announcement.scss +62 -0
  214. package/dist/organisms/navigation/_navbar-brand.scss +69 -0
  215. package/dist/organisms/navigation/_navbar-container.scss +37 -0
  216. package/dist/organisms/navigation/_navbar-desktop.scss +116 -0
  217. package/dist/organisms/navigation/_navbar-drawer.scss +97 -0
  218. package/dist/organisms/navigation/_navbar-links.scss +143 -0
  219. package/dist/organisms/navigation/_navbar-menu.scss +193 -0
  220. package/dist/organisms/navigation/_navbar-root.scss +107 -0
  221. package/dist/organisms/navigation/_navbar-search.scss +83 -0
  222. package/dist/organisms/navigation/_navbar-toggle.scss +91 -0
  223. package/dist/organisms/navigation/_navbar-tokens.scss +15 -0
  224. package/dist/organisms/navigation/navbar.scss +17 -0
  225. package/dist/registry/categories.d.ts +6 -0
  226. package/dist/registry/categories.d.ts.map +1 -0
  227. package/dist/registry/categories.js +13 -0
  228. package/dist/registry/categories.js.map +1 -0
  229. package/dist/registry/components.d.ts +5 -0
  230. package/dist/registry/components.d.ts.map +1 -0
  231. package/dist/registry/components.js +95 -0
  232. package/dist/registry/components.js.map +1 -0
  233. package/dist/registry/index.d.ts +59 -0
  234. package/dist/registry/index.d.ts.map +1 -0
  235. package/dist/registry/index.js +79 -0
  236. package/dist/registry/index.js.map +1 -0
  237. package/dist/registry/levels.d.ts +6 -0
  238. package/dist/registry/levels.d.ts.map +1 -0
  239. package/dist/registry/levels.js +9 -0
  240. package/dist/registry/levels.js.map +1 -0
  241. package/dist/registry/registry-meta-types.d.ts +67 -0
  242. package/dist/registry/registry-meta-types.d.ts.map +1 -0
  243. package/dist/registry/registry-meta-types.js +6 -0
  244. package/dist/registry/registry-meta-types.js.map +1 -0
  245. package/dist/registry/registry-meta.d.ts +5 -0
  246. package/dist/registry/registry-meta.d.ts.map +1 -0
  247. package/dist/registry/registry-meta.js +731 -0
  248. package/dist/registry/registry-meta.js.map +1 -0
  249. package/dist/registry/renderer.d.ts +69 -0
  250. package/dist/registry/renderer.d.ts.map +1 -0
  251. package/dist/registry/renderer.js +311 -0
  252. package/dist/registry/renderer.js.map +1 -0
  253. package/dist/sections/_section-base.scss +204 -0
  254. package/dist/sections/contact/ContactSection.d.ts +55 -0
  255. package/dist/sections/contact/ContactSection.d.ts.map +1 -0
  256. package/dist/sections/contact/ContactSection.js +142 -0
  257. package/dist/sections/contact/ContactSection.js.map +1 -0
  258. package/dist/sections/contact/contact-section.scss +142 -0
  259. package/dist/sections/cta/CTASection.d.ts +52 -0
  260. package/dist/sections/cta/CTASection.d.ts.map +1 -0
  261. package/dist/sections/cta/CTASection.js +130 -0
  262. package/dist/sections/cta/CTASection.js.map +1 -0
  263. package/dist/sections/cta/cta-section.scss +131 -0
  264. package/dist/sections/entrance.d.ts +29 -0
  265. package/dist/sections/entrance.d.ts.map +1 -0
  266. package/dist/sections/entrance.js +69 -0
  267. package/dist/sections/entrance.js.map +1 -0
  268. package/dist/sections/features/FeaturesSection.d.ts +54 -0
  269. package/dist/sections/features/FeaturesSection.d.ts.map +1 -0
  270. package/dist/sections/features/FeaturesSection.js +139 -0
  271. package/dist/sections/features/FeaturesSection.js.map +1 -0
  272. package/dist/sections/features/features-section.scss +140 -0
  273. package/dist/sections/footer/FooterSection.d.ts +53 -0
  274. package/dist/sections/footer/FooterSection.d.ts.map +1 -0
  275. package/dist/sections/footer/FooterSection.js +147 -0
  276. package/dist/sections/footer/FooterSection.js.map +1 -0
  277. package/dist/sections/footer/footer-section.scss +131 -0
  278. package/dist/sections/hero/HeroSection.d.ts +66 -0
  279. package/dist/sections/hero/HeroSection.d.ts.map +1 -0
  280. package/dist/sections/hero/HeroSection.js +156 -0
  281. package/dist/sections/hero/HeroSection.js.map +1 -0
  282. package/dist/sections/hero/hero-section.scss +211 -0
  283. package/dist/shared/_form-animations.scss +283 -0
  284. package/dist/shared/_media-fit.scss +63 -0
  285. package/dist/shared/_mixins.scss +69 -0
  286. package/dist/shared/_tokens.scss +116 -0
  287. package/dist/shared/badge.d.ts +15 -0
  288. package/dist/shared/badge.d.ts.map +1 -0
  289. package/dist/shared/badge.js +15 -0
  290. package/dist/shared/badge.js.map +1 -0
  291. package/dist/shared/button.d.ts +22 -0
  292. package/dist/shared/button.d.ts.map +1 -0
  293. package/dist/shared/button.js +22 -0
  294. package/dist/shared/button.js.map +1 -0
  295. package/dist/shared/card.d.ts +21 -0
  296. package/dist/shared/card.d.ts.map +1 -0
  297. package/dist/shared/card.js +38 -0
  298. package/dist/shared/card.js.map +1 -0
  299. package/dist/shared/checkbox.d.ts +10 -0
  300. package/dist/shared/checkbox.d.ts.map +1 -0
  301. package/dist/shared/checkbox.js +28 -0
  302. package/dist/shared/checkbox.js.map +1 -0
  303. package/dist/shared/clickable.d.ts +34 -0
  304. package/dist/shared/clickable.d.ts.map +1 -0
  305. package/dist/shared/clickable.js +54 -0
  306. package/dist/shared/clickable.js.map +1 -0
  307. package/dist/shared/common.d.ts +31 -0
  308. package/dist/shared/common.d.ts.map +1 -0
  309. package/dist/shared/common.js +92 -0
  310. package/dist/shared/common.js.map +1 -0
  311. package/dist/shared/entrance-config.d.ts +46 -0
  312. package/dist/shared/entrance-config.d.ts.map +1 -0
  313. package/dist/shared/entrance-config.js +54 -0
  314. package/dist/shared/entrance-config.js.map +1 -0
  315. package/dist/shared/focusable.d.ts +8 -0
  316. package/dist/shared/focusable.d.ts.map +1 -0
  317. package/dist/shared/focusable.js +17 -0
  318. package/dist/shared/focusable.js.map +1 -0
  319. package/dist/shared/form-elements.d.ts +57 -0
  320. package/dist/shared/form-elements.d.ts.map +1 -0
  321. package/dist/shared/form-elements.js +95 -0
  322. package/dist/shared/form-elements.js.map +1 -0
  323. package/dist/shared/form-state.d.ts +52 -0
  324. package/dist/shared/form-state.d.ts.map +1 -0
  325. package/dist/shared/form-state.js +151 -0
  326. package/dist/shared/form-state.js.map +1 -0
  327. package/dist/shared/grid.d.ts +21 -0
  328. package/dist/shared/grid.d.ts.map +1 -0
  329. package/dist/shared/grid.js +187 -0
  330. package/dist/shared/grid.js.map +1 -0
  331. package/dist/shared/icon-slot.d.ts +22 -0
  332. package/dist/shared/icon-slot.d.ts.map +1 -0
  333. package/dist/shared/icon-slot.js +38 -0
  334. package/dist/shared/icon-slot.js.map +1 -0
  335. package/dist/shared/icon.d.ts +17 -0
  336. package/dist/shared/icon.d.ts.map +1 -0
  337. package/dist/shared/icon.js +18 -0
  338. package/dist/shared/icon.js.map +1 -0
  339. package/dist/shared/icons.d.ts +19 -0
  340. package/dist/shared/icons.d.ts.map +1 -0
  341. package/dist/shared/icons.js +22 -0
  342. package/dist/shared/icons.js.map +1 -0
  343. package/dist/shared/image.d.ts +35 -0
  344. package/dist/shared/image.d.ts.map +1 -0
  345. package/dist/shared/image.js +46 -0
  346. package/dist/shared/image.js.map +1 -0
  347. package/dist/shared/input.d.ts +12 -0
  348. package/dist/shared/input.d.ts.map +1 -0
  349. package/dist/shared/input.js +29 -0
  350. package/dist/shared/input.js.map +1 -0
  351. package/dist/shared/radio.d.ts +10 -0
  352. package/dist/shared/radio.d.ts.map +1 -0
  353. package/dist/shared/radio.js +29 -0
  354. package/dist/shared/radio.js.map +1 -0
  355. package/dist/shared/reconcile-list.d.ts +37 -0
  356. package/dist/shared/reconcile-list.d.ts.map +1 -0
  357. package/dist/shared/reconcile-list.js +95 -0
  358. package/dist/shared/reconcile-list.js.map +1 -0
  359. package/dist/shared/section.d.ts +23 -0
  360. package/dist/shared/section.d.ts.map +1 -0
  361. package/dist/shared/section.js +65 -0
  362. package/dist/shared/section.js.map +1 -0
  363. package/dist/shared/segmented.d.ts +17 -0
  364. package/dist/shared/segmented.d.ts.map +1 -0
  365. package/dist/shared/segmented.js +53 -0
  366. package/dist/shared/segmented.js.map +1 -0
  367. package/dist/shared/select.d.ts +18 -0
  368. package/dist/shared/select.d.ts.map +1 -0
  369. package/dist/shared/select.js +14 -0
  370. package/dist/shared/select.js.map +1 -0
  371. package/dist/shared/slots.d.ts +11 -0
  372. package/dist/shared/slots.d.ts.map +1 -0
  373. package/dist/shared/slots.js +33 -0
  374. package/dist/shared/slots.js.map +1 -0
  375. package/dist/shared/smart-container.d.ts +19 -0
  376. package/dist/shared/smart-container.d.ts.map +1 -0
  377. package/dist/shared/smart-container.js +29 -0
  378. package/dist/shared/smart-container.js.map +1 -0
  379. package/dist/shared/text.d.ts +29 -0
  380. package/dist/shared/text.d.ts.map +1 -0
  381. package/dist/shared/text.js +72 -0
  382. package/dist/shared/text.js.map +1 -0
  383. package/dist/shared/textarea.d.ts +6 -0
  384. package/dist/shared/textarea.d.ts.map +1 -0
  385. package/dist/shared/textarea.js +18 -0
  386. package/dist/shared/textarea.js.map +1 -0
  387. package/dist/shared/toggle.d.ts +6 -0
  388. package/dist/shared/toggle.d.ts.map +1 -0
  389. package/dist/shared/toggle.js +19 -0
  390. package/dist/shared/toggle.js.map +1 -0
  391. package/dist/shared/types.d.ts +41 -0
  392. package/dist/shared/types.d.ts.map +1 -0
  393. package/dist/shared/types.js +20 -0
  394. package/dist/shared/types.js.map +1 -0
  395. package/dist/structural/ErrorBoundary.d.ts +18 -0
  396. package/dist/structural/ErrorBoundary.d.ts.map +1 -0
  397. package/dist/structural/ErrorBoundary.js +119 -0
  398. package/dist/structural/ErrorBoundary.js.map +1 -0
  399. package/dist/structural/For.d.ts +37 -0
  400. package/dist/structural/For.d.ts.map +1 -0
  401. package/dist/structural/For.js +129 -0
  402. package/dist/structural/For.js.map +1 -0
  403. package/dist/structural/Lazy.d.ts +43 -0
  404. package/dist/structural/Lazy.d.ts.map +1 -0
  405. package/dist/structural/Lazy.js +47 -0
  406. package/dist/structural/Lazy.js.map +1 -0
  407. package/dist/structural/NavLink.d.ts +45 -0
  408. package/dist/structural/NavLink.d.ts.map +1 -0
  409. package/dist/structural/NavLink.js +37 -0
  410. package/dist/structural/NavLink.js.map +1 -0
  411. package/dist/structural/Show.d.ts +35 -0
  412. package/dist/structural/Show.d.ts.map +1 -0
  413. package/dist/structural/Show.js +34 -0
  414. package/dist/structural/Show.js.map +1 -0
  415. package/dist/structural/nav-link.scss +54 -0
  416. package/dist/styles/index.scss +58 -0
  417. package/package.json +64 -0
@@ -0,0 +1,66 @@
1
+ /// Icon component styles
2
+ /// Accessible inline icon wrapper sized by design-system iconography tokens.
3
+ /// Uses currentColor inheritance — zero raw values.
4
+ ///
5
+ /// @group atoms/content
6
+
7
+ @use '@pithyjs/design-system/iconography/_generated/tokens' as icon-tokens;
8
+ @use '../mixins' as content;
9
+
10
+ // ============================================
11
+ // Base wrapper — inline icon container
12
+ // ============================================
13
+
14
+ .ui-icon {
15
+ // Inline-flex keeps icon inline with text while centering SVG content
16
+ display: inline-flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+ // Shrink-to-fit — default md size (overridden by u-icon-* utilities)
20
+ inline-size: icon-tokens.icon-size-var(md);
21
+ block-size: icon-tokens.icon-size-var(md);
22
+ // Inherit parent text color by default
23
+ color: currentColor;
24
+ // Ensure SVG children fill the container
25
+ line-height: 0;
26
+ // Clip overflow — fixed-size box should not leak content beyond its bounds
27
+ overflow: hidden;
28
+ // Prevent icon from shrinking in flex layouts
29
+ flex-shrink: 0;
30
+ // Optical alignment with adjacent text
31
+ vertical-align: middle;
32
+
33
+ // SVG children should fill the icon container.
34
+ // No fill/stroke override — SVGs control their own rendering:
35
+ // Solid icons: use fill="currentColor" (or inherit from parent color)
36
+ // Outline icons: use fill="none" stroke="currentColor"
37
+ // This avoids CSS fill overriding SVG presentation attributes.
38
+ > svg {
39
+ inline-size: 100%;
40
+ block-size: 100%;
41
+ }
42
+ }
43
+
44
+ // ============================================
45
+ // Size variants (from --icon-size-* tokens)
46
+ // ============================================
47
+
48
+ @each $level, $_value in icon-tokens.$size-tokens {
49
+ .u-icon-#{$level} {
50
+ inline-size: icon-tokens.icon-size-var($level);
51
+ block-size: icon-tokens.icon-size-var($level);
52
+ }
53
+ }
54
+
55
+ // ============================================
56
+ // Color scheme (maps data-color to --color-* tokens)
57
+ // ============================================
58
+
59
+ @include content.color-scheme('.ui-icon');
60
+
61
+ // ============================================
62
+ // High Contrast (forced-colors + increased contrast)
63
+ // ============================================
64
+
65
+ @include content.forced-colors('.ui-icon');
66
+ @include content.high-contrast('.ui-icon');
@@ -0,0 +1,21 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.ui-kit.icon-resolve",
4
+ "title": "Icon Sprite SVG Resolution",
5
+ "category": "runtime"
6
+ }
7
+ */
8
+ export interface ResolvedIcon {
9
+ /** The SVG element to append */
10
+ svg: SVGSVGElement;
11
+ /** Whether this is a missing-icon placeholder */
12
+ missing: boolean;
13
+ }
14
+ /**
15
+ * Try to resolve `name` from the icon sprite registry.
16
+ *
17
+ * @returns A resolved icon with `svg` and `missing` flag, or `null` if no name was provided.
18
+ */
19
+ /** @codexApi {"parent":"pithy.ui-kit.icon-resolve","name":"resolveIconSvg","stability":"stable","signature":"(name: string | undefined) => ResolvedIcon | null"} */
20
+ export declare function resolveIconSvg(name: string | undefined): ResolvedIcon | null;
21
+ //# sourceMappingURL=resolveIconSvg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveIconSvg.d.ts","sourceRoot":"","sources":["../../../../src/atoms/content/icon/resolveIconSvg.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAiBF,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,GAAG,EAAE,aAAa,CAAC;IACnB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,oKAAoK;AACpK,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CA2B5E"}
@@ -0,0 +1,73 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.ui-kit.icon-resolve",
4
+ "title": "Icon Sprite SVG Resolution",
5
+ "category": "runtime"
6
+ }
7
+ */
8
+ /**
9
+ * Resolve an icon name to an SVG element from the sprite registry.
10
+ *
11
+ * Returns a ready-to-append `<svg>` element:
12
+ * - Found → `<svg><use href="sprite#name"/></svg>`
13
+ * - Not found → placeholder (dashed circle + "?") with DEV warning
14
+ * - No name → `null`
15
+ */
16
+ // Relative import to avoid self-referencing package alias (@pithyjs/ui-kit/icons).
17
+ // Maps to: packages/ui-kit/src/icons/index.ts
18
+ import { lookupIcon } from '../../../icons';
19
+ const SVG_NS = 'http://www.w3.org/2000/svg';
20
+ /**
21
+ * Try to resolve `name` from the icon sprite registry.
22
+ *
23
+ * @returns A resolved icon with `svg` and `missing` flag, or `null` if no name was provided.
24
+ */
25
+ /** @codexApi {"parent":"pithy.ui-kit.icon-resolve","name":"resolveIconSvg","stability":"stable","signature":"(name: string | undefined) => ResolvedIcon | null"} */
26
+ export function resolveIconSvg(name) {
27
+ const trimmed = name?.trim();
28
+ if (!trimmed)
29
+ return null;
30
+ const result = lookupIcon(trimmed);
31
+ if (result) {
32
+ const svg = document.createElementNS(SVG_NS, 'svg');
33
+ svg.setAttribute('aria-hidden', 'true');
34
+ if (result.viewBox) {
35
+ svg.setAttribute('viewBox', result.viewBox);
36
+ }
37
+ const use = document.createElementNS(SVG_NS, 'use');
38
+ use.setAttribute('href', result.href);
39
+ svg.appendChild(use);
40
+ return { svg, missing: false };
41
+ }
42
+ // Missing icon — placeholder: dashed circle + "?"
43
+ if (import.meta.env?.DEV) {
44
+ console.warn(`[<Icon>] name="${name}" not found in icon registry and no children provided. ` +
45
+ `Either register a sprite with registerIconSprite() or pass inline SVG as children.`);
46
+ }
47
+ return { svg: createMissingIconSvg(), missing: true };
48
+ }
49
+ function createMissingIconSvg() {
50
+ const svg = document.createElementNS(SVG_NS, 'svg');
51
+ svg.setAttribute('aria-hidden', 'true');
52
+ svg.setAttribute('viewBox', '0 0 24 24');
53
+ svg.setAttribute('fill', 'none');
54
+ svg.setAttribute('stroke', 'currentColor');
55
+ svg.setAttribute('stroke-width', '1.5');
56
+ const circle = document.createElementNS(SVG_NS, 'circle');
57
+ circle.setAttribute('cx', '12');
58
+ circle.setAttribute('cy', '12');
59
+ circle.setAttribute('r', '10');
60
+ circle.setAttribute('stroke-dasharray', '4 3');
61
+ svg.appendChild(circle);
62
+ const text = document.createElementNS(SVG_NS, 'text');
63
+ text.setAttribute('x', '12');
64
+ text.setAttribute('y', '16');
65
+ text.setAttribute('text-anchor', 'middle');
66
+ text.setAttribute('fill', 'currentColor');
67
+ text.setAttribute('stroke', 'none');
68
+ text.setAttribute('font-size', '12');
69
+ text.textContent = '?';
70
+ svg.appendChild(text);
71
+ return svg;
72
+ }
73
+ //# sourceMappingURL=resolveIconSvg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveIconSvg.js","sourceRoot":"","sources":["../../../../src/atoms/content/icon/resolveIconSvg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.ui-kit.image",
4
+ "title": "<Image> Content Component",
5
+ "category": "feature"
6
+ }
7
+ */
8
+ import type { ReactiveText } from '../../../shared/clickable';
9
+ import { type ImageFit, type ImageLoading, type ImageDecoding, type ImageFetchPriority, type ImageSizing } from '../../../shared/image';
10
+ import { type RadiusLevel } from '@pithyjs/design-system/radius';
11
+ /** @codexApi {"parent":"pithy.ui-kit.image","name":"ImageSource","stability":"stable","signature":"interface ImageSource"} */
12
+ /**
13
+ * A single `<source>` entry for `<picture>` multi-format rendering.
14
+ * Each source must have at least one of `src` or `srcset`.
15
+ *
16
+ * Note: the root-level `ImageProps.src` is always required for the fallback
17
+ * `<img>` element. These sources only add `<source>` alternatives inside
18
+ * `<picture>` — they do not replace the root `src`.
19
+ */
20
+ export interface ImageSource {
21
+ /** Image URL — required if `srcset` is not provided */
22
+ src?: string;
23
+ /** MIME type (e.g. "image/avif", "image/webp") */
24
+ type?: string;
25
+ /** Media condition (e.g. "(min-width: 768px)") */
26
+ media?: string;
27
+ /** Srcset descriptor (e.g. "img.avif 1x, img.avif 2x" or "img-400.avif 400w") */
28
+ srcset?: string;
29
+ }
30
+ /** @codexApi {"parent":"pithy.ui-kit.image","name":"ImageProps","stability":"stable","signature":"interface ImageProps"} */
31
+ export interface ImageProps {
32
+ /** Image source URL — static string or signal/computed accessor. Required. */
33
+ src: ReactiveText;
34
+ /** Alt text for accessibility — static or signal. REQUIRED. Use "" only for purely decorative images. */
35
+ alt: ReactiveText;
36
+ /** Intrinsic width in pixels — prevents layout shift (CLS) */
37
+ width?: number;
38
+ /** Intrinsic height in pixels — prevents layout shift (CLS) */
39
+ height?: number;
40
+ /** Loading strategy (default: "lazy") */
41
+ loading?: ImageLoading;
42
+ /** Decoding strategy (default: "async") */
43
+ decoding?: ImageDecoding;
44
+ /** Fetch priority hint — use "high" for LCP images (default: "auto") */
45
+ fetchPriority?: ImageFetchPriority;
46
+ /** Aspect ratio — preset string ("16/9") or custom CSS value ("4 / 3") */
47
+ aspectRatio?: string;
48
+ /** Object-fit — how the image fills its container (default: "cover") */
49
+ fit?: ImageFit;
50
+ /** Width behaviour — "auto" (intrinsic, capped at 100%) or "fill" (100% of container). Default: "auto". */
51
+ sizing?: ImageSizing;
52
+ /** Responsive sizes attribute (e.g. "(max-width: 600px) 100vw, 50vw") */
53
+ sizes?: string;
54
+ /** Srcset for responsive resolution switching (e.g. "img-400.jpg 400w, img-800.jpg 800w") */
55
+ srcset?: string;
56
+ /** Additional <source> elements for <picture> — enables AVIF/WebP with fallback */
57
+ sources?: ImageSource[];
58
+ /** Border radius — design system RadiusLevel or true for "md" (default: none) */
59
+ rounded?: boolean | RadiusLevel;
60
+ }
61
+ /**
62
+ * Accessible, optimized image component.
63
+ *
64
+ * Mobile-first with lazy loading and async decoding by default.
65
+ * Enforces `alt` text for accessibility. Use `width`/`height` to eliminate
66
+ * layout shift (CLS = 0). Supports `<picture>` with multiple `<source>`
67
+ * elements for format negotiation (AVIF, WebP, fallback).
68
+ *
69
+ * @example
70
+ * ```html
71
+ * <Image src="'/photo.jpg'" alt="'A sunset'" width="800" height="600" />
72
+ * <Image src="'/hero.jpg'" alt="'Hero'" aspectRatio="'16/9'" fit="'cover'" loading="'eager'" fetchPriority="'high'" />
73
+ * <Image src="'/avatar.jpg'" alt="'User'" width="100" height="100" rounded="'xl'" />
74
+ * ```
75
+ */
76
+ /** @codexApi {"parent":"pithy.ui-kit.image","name":"Image","stability":"stable","signature":"(props: ImageProps) => { el: HTMLElement | DocumentFragment; destroy: () => void }"} */
77
+ export declare function Image(props: ImageProps): {
78
+ el: HTMLElement | DocumentFragment;
79
+ destroy: () => void;
80
+ };
81
+ //# sourceMappingURL=Image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../../src/atoms/content/image/Image.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAKF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAOL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAIhF,8HAA8H;AAC9H;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4HAA4H;AAC5H,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,GAAG,EAAE,YAAY,CAAC;IAClB,yGAAyG;IACzG,GAAG,EAAE,YAAY,CAAC;IAClB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,wEAAwE;IACxE,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,2GAA2G;IAC3G,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,iFAAiF;IACjF,OAAO,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,qLAAqL;AACrL,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG;IACxC,EAAE,EAAE,WAAW,GAAG,gBAAgB,CAAC;IACnC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAkVA"}
@@ -0,0 +1,293 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.ui-kit.image",
4
+ "title": "<Image> Content Component",
5
+ "category": "feature"
6
+ }
7
+ */
8
+ import { renderChildren } from '@pithyjs/core';
9
+ import { captureSlot } from '../../../shared/slots';
10
+ import { effect } from '@pithyjs/signals';
11
+ import { IMAGE_FIT_VALUES, IMAGE_LOADING_VALUES, IMAGE_DECODING_VALUES, IMAGE_FETCH_PRIORITY_VALUES, IMAGE_SIZING_VALUES, ASPECT_RATIO_PRESETS, } from '../../../shared/image';
12
+ import { RADIUS_LEVELS } from '@pithyjs/design-system/radius';
13
+ /**
14
+ * Accessible, optimized image component.
15
+ *
16
+ * Mobile-first with lazy loading and async decoding by default.
17
+ * Enforces `alt` text for accessibility. Use `width`/`height` to eliminate
18
+ * layout shift (CLS = 0). Supports `<picture>` with multiple `<source>`
19
+ * elements for format negotiation (AVIF, WebP, fallback).
20
+ *
21
+ * @example
22
+ * ```html
23
+ * <Image src="'/photo.jpg'" alt="'A sunset'" width="800" height="600" />
24
+ * <Image src="'/hero.jpg'" alt="'Hero'" aspectRatio="'16/9'" fit="'cover'" loading="'eager'" fetchPriority="'high'" />
25
+ * <Image src="'/avatar.jpg'" alt="'User'" width="100" height="100" rounded="'xl'" />
26
+ * ```
27
+ */
28
+ /** @codexApi {"parent":"pithy.ui-kit.image","name":"Image","stability":"stable","signature":"(props: ImageProps) => { el: HTMLElement | DocumentFragment; destroy: () => void }"} */
29
+ export function Image(props) {
30
+ const { src: srcProp, alt: altProp, width, height, loading: rawLoading = 'lazy', decoding: rawDecoding = 'async', fetchPriority: rawFetchPriority = 'auto', aspectRatio: rawAspectRatio, fit: rawFit = 'cover', sizing: rawSizing = 'auto', sizes, srcset, sources, rounded, } = props;
31
+ const isSrcFn = typeof srcProp === 'function';
32
+ const isAltFn = typeof altProp === 'function';
33
+ const readSrc = () => isSrcFn
34
+ ? srcProp()
35
+ : srcProp;
36
+ const readAlt = () => isAltFn
37
+ ? altProp()
38
+ : altProp;
39
+ const staticSrc = isSrcFn ? undefined : readSrc();
40
+ const staticAlt = isAltFn ? undefined : readAlt();
41
+ // -- Validation -----------------------------------------------------------
42
+ const hasSrc = typeof staticSrc === 'string' && staticSrc.trim().length > 0;
43
+ // Whitespace-only alt is treated as missing (warned in DEV); intentionally
44
+ // empty alt ("") is allowed and marks the image as decorative.
45
+ const isValidAlt = (v) => typeof v === 'string' && (v === '' || v.trim().length > 0);
46
+ const hasAlt = isValidAlt(staticAlt);
47
+ const validLoading = IMAGE_LOADING_VALUES.includes(rawLoading);
48
+ const validDecoding = IMAGE_DECODING_VALUES.includes(rawDecoding);
49
+ const validFetchPriority = IMAGE_FETCH_PRIORITY_VALUES.includes(rawFetchPriority);
50
+ const validFit = IMAGE_FIT_VALUES.includes(rawFit);
51
+ const sizing = IMAGE_SIZING_VALUES.includes(rawSizing)
52
+ ? rawSizing
53
+ : 'auto';
54
+ // Sanitize width/height: must be finite positive integers (at least 1px)
55
+ const validWidth = width != null && Number.isFinite(width) && width > 0
56
+ ? Math.max(1, Math.round(width))
57
+ : undefined;
58
+ const validHeight = height != null && Number.isFinite(height) && height > 0
59
+ ? Math.max(1, Math.round(height))
60
+ : undefined;
61
+ // Validate rounded prop
62
+ const validRounded = rounded === true
63
+ ? 'md'
64
+ : typeof rounded === 'string' &&
65
+ RADIUS_LEVELS.includes(rounded)
66
+ ? rounded
67
+ : undefined;
68
+ if (import.meta.env?.DEV) {
69
+ if (!isSrcFn && !hasSrc) {
70
+ console.warn(`[<Image>] Missing or empty "src" prop. An image source is required.`);
71
+ }
72
+ if (!isAltFn && !hasAlt) {
73
+ console.warn(`[<Image>] Missing "alt" prop. All images MUST have alt text for accessibility. Use alt="" only for purely decorative images.`);
74
+ }
75
+ if (!validLoading) {
76
+ const valid = IMAGE_LOADING_VALUES.join(', ');
77
+ console.warn(`[<Image>] Invalid loading: "${rawLoading}". Expected one of: ${valid}. Falling back to "lazy".`);
78
+ }
79
+ if (!validDecoding) {
80
+ const valid = IMAGE_DECODING_VALUES.join(', ');
81
+ console.warn(`[<Image>] Invalid decoding: "${rawDecoding}". Expected one of: ${valid}. Falling back to "async".`);
82
+ }
83
+ if (!validFetchPriority) {
84
+ const valid = IMAGE_FETCH_PRIORITY_VALUES.join(', ');
85
+ console.warn(`[<Image>] Invalid fetchPriority: "${rawFetchPriority}". Expected one of: ${valid}. Falling back to "auto".`);
86
+ }
87
+ if (!validFit) {
88
+ const valid = IMAGE_FIT_VALUES.join(', ');
89
+ console.warn(`[<Image>] Invalid fit: "${rawFit}". Expected one of: ${valid}. Falling back to "cover".`);
90
+ }
91
+ if (rawLoading === 'lazy' && rawFetchPriority === 'high') {
92
+ console.warn(`[<Image>] loading="lazy" with fetchPriority="high" is contradictory. For LCP images, use loading="eager" with fetchPriority="high".`);
93
+ }
94
+ if (width == null || height == null) {
95
+ console.warn(`[<Image>] Missing width/height. Provide both to prevent layout shift (CLS). The browser needs intrinsic dimensions to reserve space before the image loads.`);
96
+ }
97
+ if (width != null && (!Number.isFinite(width) || width <= 0)) {
98
+ console.warn(`[<Image>] Invalid width: ${width}. Expected a finite positive number. Ignoring.`);
99
+ }
100
+ if (height != null && (!Number.isFinite(height) || height <= 0)) {
101
+ console.warn(`[<Image>] Invalid height: ${height}. Expected a finite positive number. Ignoring.`);
102
+ }
103
+ if (rounded != null &&
104
+ rounded !== true &&
105
+ rounded !== false &&
106
+ !validRounded) {
107
+ const valid = RADIUS_LEVELS.join(', ');
108
+ console.warn(`[<Image>] Invalid rounded: "${rounded}". Expected true or one of: ${valid}. Ignoring.`);
109
+ }
110
+ if (sources != null && !Array.isArray(sources)) {
111
+ console.warn(`[<Image>] Invalid "sources" prop: expected an array of ImageSource objects. Falling back to plain <img>.`);
112
+ }
113
+ if (Array.isArray(sources) &&
114
+ sources.some(s => s == null ||
115
+ typeof s !== 'object' ||
116
+ ((typeof s.src !== 'string' || s.src.trim().length === 0) &&
117
+ (typeof s.srcset !== 'string' || s.srcset.trim().length === 0)))) {
118
+ console.warn(`[<Image>] Some entries in "sources" are invalid: each source must be an object with a non-empty "src" or "srcset" string.`);
119
+ }
120
+ }
121
+ const loading = validLoading ? rawLoading : 'lazy';
122
+ const decoding = validDecoding ? rawDecoding : 'async';
123
+ const fetchPriority = validFetchPriority ? rawFetchPriority : 'auto';
124
+ const fit = validFit ? rawFit : 'cover';
125
+ // Resolve aspect ratio (preset or custom CSS value)
126
+ const aspectRatio = rawAspectRatio
127
+ ? ASPECT_RATIO_PRESETS[rawAspectRatio] || rawAspectRatio
128
+ : undefined;
129
+ // -- Determine rendering mode: <picture> or plain <img> -------------------
130
+ const usePicture = Array.isArray(sources) && sources.length > 0;
131
+ // -- Build wrapper element ------------------------------------------------
132
+ const el = document.createElement('div');
133
+ el.classList.add('ui-image');
134
+ if (sizing === 'fill') {
135
+ el.dataset.sizing = 'fill';
136
+ }
137
+ // Aspect ratio container
138
+ if (aspectRatio) {
139
+ el.style.aspectRatio = aspectRatio;
140
+ el.classList.add('ui-image-aspect-ratio');
141
+ }
142
+ // Rounded corners — maps to design system u-radius-* utilities
143
+ if (validRounded) {
144
+ el.classList.add(`u-radius-${validRounded}`);
145
+ }
146
+ // Width/height on wrapper to reserve space (CLS prevention)
147
+ if (validWidth != null && !aspectRatio) {
148
+ el.style.maxInlineSize = `${validWidth}px`;
149
+ }
150
+ // -- Build image content or empty placeholder -----------------------------
151
+ // Applied separately so buildImageContent doesn't subscribe its caller to alt.
152
+ const applyAlt = (target, value) => {
153
+ if (isValidAlt(value)) {
154
+ target.alt = value;
155
+ if (value === '')
156
+ target.setAttribute('role', 'none');
157
+ else
158
+ target.removeAttribute('role');
159
+ }
160
+ else {
161
+ target.removeAttribute('alt');
162
+ target.removeAttribute('role');
163
+ }
164
+ };
165
+ const buildImageContent = (src) => {
166
+ const newImg = document.createElement('img');
167
+ newImg.classList.add('ui-image-img');
168
+ newImg.src = src;
169
+ newImg.loading = loading;
170
+ newImg.decoding = decoding;
171
+ if (fetchPriority !== 'auto') {
172
+ newImg.setAttribute('fetchpriority', fetchPriority);
173
+ }
174
+ if (validWidth != null)
175
+ newImg.width = validWidth;
176
+ if (validHeight != null)
177
+ newImg.height = validHeight;
178
+ if (fit)
179
+ newImg.style.objectFit = fit;
180
+ if (typeof sizes === 'string') {
181
+ const trimmedSizes = sizes.trim();
182
+ if (trimmedSizes.length > 0)
183
+ newImg.sizes = trimmedSizes;
184
+ }
185
+ if (typeof srcset === 'string') {
186
+ const trimmedSrcset = srcset.trim();
187
+ if (trimmedSrcset.length > 0)
188
+ newImg.srcset = trimmedSrcset;
189
+ }
190
+ const pictureSources = usePicture ? sources : [];
191
+ if (pictureSources.length === 0)
192
+ return { root: newImg, img: newImg };
193
+ const picture = document.createElement('picture');
194
+ picture.classList.add('ui-image-picture');
195
+ for (const source of pictureSources) {
196
+ const trimmedSrc = typeof source?.src === 'string' ? source.src.trim() : '';
197
+ const trimmedSrcset = typeof source?.srcset === 'string' ? source.srcset.trim() : '';
198
+ if (source == null ||
199
+ typeof source !== 'object' ||
200
+ (!trimmedSrc && !trimmedSrcset)) {
201
+ continue;
202
+ }
203
+ const sourceEl = document.createElement('source');
204
+ sourceEl.srcset = trimmedSrcset || trimmedSrc;
205
+ if (typeof source.type === 'string') {
206
+ const trimmedType = source.type.trim();
207
+ if (trimmedType)
208
+ sourceEl.type = trimmedType;
209
+ }
210
+ if (typeof source.media === 'string') {
211
+ const trimmedMedia = source.media.trim();
212
+ if (trimmedMedia)
213
+ sourceEl.media = trimmedMedia;
214
+ }
215
+ if (typeof sizes === 'string') {
216
+ const trimmedSizes = sizes.trim();
217
+ if (trimmedSizes.length > 0)
218
+ sourceEl.sizes = trimmedSizes;
219
+ }
220
+ picture.appendChild(sourceEl);
221
+ }
222
+ if (picture.childElementCount === 0)
223
+ return { root: newImg, img: newImg };
224
+ picture.appendChild(newImg);
225
+ return { root: picture, img: newImg };
226
+ };
227
+ let img;
228
+ let contentRoot;
229
+ if (hasSrc) {
230
+ const built = buildImageContent(staticSrc.trim());
231
+ contentRoot = built.root;
232
+ img = built.img;
233
+ if (!isAltFn)
234
+ applyAlt(img, staticAlt);
235
+ el.appendChild(contentRoot);
236
+ }
237
+ else {
238
+ // No valid src — render an empty placeholder to avoid a spurious
239
+ // network request (setting img.src="" resolves to the document URL).
240
+ el.classList.add('ui-image-empty');
241
+ }
242
+ // Content projection (for overlay content like captions). Anchored after the
243
+ // image so reactive remounts can insertBefore() to preserve DOM order.
244
+ const { el: childFragment, destroy } = renderChildren();
245
+ captureSlot(el, 'default');
246
+ const childAnchor = document.createComment('');
247
+ el.appendChild(childAnchor);
248
+ el.appendChild(childFragment);
249
+ // Reactive src — handles empty ↔ non-empty transitions by mounting/unmounting
250
+ // the <img>/<picture>. Static-string src never changes, so we skip the effect.
251
+ const cleanupSrcEffect = isSrcFn
252
+ ? effect(() => {
253
+ const next = readSrc();
254
+ const trimmed = typeof next === 'string' ? next.trim() : '';
255
+ if (trimmed.length > 0) {
256
+ if (img) {
257
+ img.src = trimmed;
258
+ }
259
+ else {
260
+ const built = buildImageContent(trimmed);
261
+ contentRoot = built.root;
262
+ img = built.img;
263
+ applyAlt(img, isAltFn ? readAlt() : staticAlt);
264
+ el.classList.remove('ui-image-empty');
265
+ el.insertBefore(contentRoot, childAnchor);
266
+ }
267
+ }
268
+ else if (contentRoot) {
269
+ contentRoot.remove();
270
+ contentRoot = undefined;
271
+ img = undefined;
272
+ el.classList.add('ui-image-empty');
273
+ }
274
+ })
275
+ : undefined;
276
+ const cleanupAltEffect = isAltFn
277
+ ? effect(() => {
278
+ const next = readAlt();
279
+ if (img)
280
+ applyAlt(img, next);
281
+ })
282
+ : undefined;
283
+ return {
284
+ el,
285
+ destroy: () => {
286
+ cleanupSrcEffect?.();
287
+ cleanupAltEffect?.();
288
+ destroy();
289
+ el.replaceChildren();
290
+ },
291
+ };
292
+ }
293
+ //# sourceMappingURL=Image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Image.js","sourceRoot":"","sources":["../../../../src/atoms/content/image/Image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /// Image component styles
2
+ /// Optimized, accessible image rendering with CLS prevention.
3
+ /// Uses design system tokens -- zero raw values.
4
+ ///
5
+ /// @group atoms/content
6
+
7
+ @use '@pithyjs/design-system/a11y/styles/mixins' as a11y;
8
+
9
+ // ============================================
10
+ // Base wrapper — reserves space, prevents CLS
11
+ // ============================================
12
+
13
+ .ui-image {
14
+ // Block element by default for layout control
15
+ display: block;
16
+ position: relative;
17
+ // Prevent overflow from rounded corners or aspect ratio
18
+ overflow: hidden;
19
+ // Logical max-width: never exceed container
20
+ max-inline-size: 100%;
21
+ // Intrinsic sizing: shrink-to-fit by default
22
+ inline-size: fit-content;
23
+
24
+ &[data-sizing='fill'] {
25
+ inline-size: 100%;
26
+ }
27
+ }
28
+
29
+ // ============================================
30
+ // <img> element — fills the container
31
+ // ============================================
32
+
33
+ .ui-image-img {
34
+ // Fill the wrapper completely
35
+ display: block;
36
+ inline-size: 100%;
37
+ block-size: 100%;
38
+ }
39
+
40
+ // When aspect ratio is set on the wrapper, img fills it
41
+ .ui-image-aspect-ratio .ui-image-img {
42
+ // Ensure image fills the entire aspect ratio box
43
+ object-fit: cover;
44
+ block-size: 100%;
45
+ }
46
+
47
+ // ============================================
48
+ // <picture> element — transparent wrapper
49
+ // ============================================
50
+
51
+ .ui-image-picture {
52
+ display: contents;
53
+ }
54
+
55
+ // ============================================
56
+ // High Contrast (forced-colors)
57
+ // ============================================
58
+
59
+ @include a11y.forced-colors {
60
+ // In high contrast mode, ensure images remain visible.
61
+ // Add a thin border so users know an image is present.
62
+ .ui-image {
63
+ border: var(--border-width-hairline) solid CanvasText;
64
+ }
65
+ }
66
+
67
+ // ============================================
68
+ // Reduced motion — pause CSS animations on images
69
+ // ============================================
70
+
71
+ @include a11y.motion-reduced {
72
+ .ui-image-img {
73
+ // Pause any CSS animations applied to the <img> when reduced motion is requested
74
+ // Note: this does not stop GIF/APNG playback; it only affects CSS-driven animations
75
+ animation-play-state: paused;
76
+ }
77
+ }