@number10/jsx-core 5.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 (340) hide show
  1. package/LICENSE +667 -0
  2. package/README.md +38 -0
  3. package/dist/animation/animated-signal.cjs +19 -0
  4. package/dist/animation/animated-signal.cjs.map +1 -0
  5. package/dist/animation/animated-signal.d.ts +35 -0
  6. package/dist/animation/animated-signal.d.ts.map +1 -0
  7. package/dist/animation/animated-signal.js +19 -0
  8. package/dist/animation/animated-signal.js.map +1 -0
  9. package/dist/animation/create-spring.cjs +80 -0
  10. package/dist/animation/create-spring.cjs.map +1 -0
  11. package/dist/animation/create-spring.d.ts +56 -0
  12. package/dist/animation/create-spring.d.ts.map +1 -0
  13. package/dist/animation/create-spring.js +80 -0
  14. package/dist/animation/create-spring.js.map +1 -0
  15. package/dist/animation/easing.cjs +76 -0
  16. package/dist/animation/easing.cjs.map +1 -0
  17. package/dist/animation/easing.d.ts +45 -0
  18. package/dist/animation/easing.d.ts.map +1 -0
  19. package/dist/animation/easing.js +76 -0
  20. package/dist/animation/easing.js.map +1 -0
  21. package/dist/animation/effect-definitions.cjs +441 -0
  22. package/dist/animation/effect-definitions.cjs.map +1 -0
  23. package/dist/animation/effect-definitions.d.ts +60 -0
  24. package/dist/animation/effect-definitions.d.ts.map +1 -0
  25. package/dist/animation/effect-definitions.js +441 -0
  26. package/dist/animation/effect-definitions.js.map +1 -0
  27. package/dist/animation/effect-engine.cjs +189 -0
  28. package/dist/animation/effect-engine.cjs.map +1 -0
  29. package/dist/animation/effect-engine.d.ts +70 -0
  30. package/dist/animation/effect-engine.d.ts.map +1 -0
  31. package/dist/animation/effect-engine.js +189 -0
  32. package/dist/animation/effect-engine.js.map +1 -0
  33. package/dist/animation/index.d.ts +24 -0
  34. package/dist/animation/index.d.ts.map +1 -0
  35. package/dist/animation/spring-physics.cjs +94 -0
  36. package/dist/animation/spring-physics.cjs.map +1 -0
  37. package/dist/animation/spring-physics.d.ts +145 -0
  38. package/dist/animation/spring-physics.d.ts.map +1 -0
  39. package/dist/animation/spring-physics.js +94 -0
  40. package/dist/animation/spring-physics.js.map +1 -0
  41. package/dist/animation/tween.cjs +67 -0
  42. package/dist/animation/tween.cjs.map +1 -0
  43. package/dist/animation/tween.d.ts +60 -0
  44. package/dist/animation/tween.d.ts.map +1 -0
  45. package/dist/animation/tween.js +67 -0
  46. package/dist/animation/tween.js.map +1 -0
  47. package/dist/animation/types.d.ts +31 -0
  48. package/dist/animation/types.d.ts.map +1 -0
  49. package/dist/animation/useSpring.cjs +152 -0
  50. package/dist/animation/useSpring.cjs.map +1 -0
  51. package/dist/animation/useSpring.d.ts +55 -0
  52. package/dist/animation/useSpring.d.ts.map +1 -0
  53. package/dist/animation/useSpring.js +149 -0
  54. package/dist/animation/useSpring.js.map +1 -0
  55. package/dist/animation/useTween.cjs +208 -0
  56. package/dist/animation/useTween.cjs.map +1 -0
  57. package/dist/animation/useTween.d.ts +116 -0
  58. package/dist/animation/useTween.d.ts.map +1 -0
  59. package/dist/animation/useTween.js +208 -0
  60. package/dist/animation/useTween.js.map +1 -0
  61. package/dist/border-geometry.cjs +447 -0
  62. package/dist/border-geometry.cjs.map +1 -0
  63. package/dist/border-geometry.d.ts +114 -0
  64. package/dist/border-geometry.d.ts.map +1 -0
  65. package/dist/border-geometry.js +447 -0
  66. package/dist/border-geometry.js.map +1 -0
  67. package/dist/colors/color-presets.cjs +236 -0
  68. package/dist/colors/color-presets.cjs.map +1 -0
  69. package/dist/colors/color-presets.d.ts +89 -0
  70. package/dist/colors/color-presets.d.ts.map +1 -0
  71. package/dist/colors/color-presets.js +236 -0
  72. package/dist/colors/color-presets.js.map +1 -0
  73. package/dist/colors/color-theme-helpers.cjs +32 -0
  74. package/dist/colors/color-theme-helpers.cjs.map +1 -0
  75. package/dist/colors/color-theme-helpers.d.ts +65 -0
  76. package/dist/colors/color-theme-helpers.d.ts.map +1 -0
  77. package/dist/colors/color-theme-helpers.js +32 -0
  78. package/dist/colors/color-theme-helpers.js.map +1 -0
  79. package/dist/colors/color-types.cjs +38 -0
  80. package/dist/colors/color-types.cjs.map +1 -0
  81. package/dist/colors/color-types.d.ts +112 -0
  82. package/dist/colors/color-types.d.ts.map +1 -0
  83. package/dist/colors/color-types.js +38 -0
  84. package/dist/colors/color-types.js.map +1 -0
  85. package/dist/colors/color-utils.cjs +197 -0
  86. package/dist/colors/color-utils.cjs.map +1 -0
  87. package/dist/colors/color-utils.d.ts +216 -0
  88. package/dist/colors/color-utils.d.ts.map +1 -0
  89. package/dist/colors/color-utils.js +197 -0
  90. package/dist/colors/color-utils.js.map +1 -0
  91. package/dist/colors/contrast-contracts.cjs +265 -0
  92. package/dist/colors/contrast-contracts.cjs.map +1 -0
  93. package/dist/colors/contrast-contracts.d.ts +289 -0
  94. package/dist/colors/contrast-contracts.d.ts.map +1 -0
  95. package/dist/colors/contrast-contracts.js +265 -0
  96. package/dist/colors/contrast-contracts.js.map +1 -0
  97. package/dist/colors/index.cjs +55 -0
  98. package/dist/colors/index.cjs.map +1 -0
  99. package/dist/colors/index.d.ts +16 -0
  100. package/dist/colors/index.d.ts.map +1 -0
  101. package/dist/colors/index.js +55 -0
  102. package/dist/colors/index.js.map +1 -0
  103. package/dist/core-props.cjs +66 -0
  104. package/dist/core-props.cjs.map +1 -0
  105. package/dist/core-props.d.ts +395 -0
  106. package/dist/core-props.d.ts.map +1 -0
  107. package/dist/core-props.js +66 -0
  108. package/dist/core-props.js.map +1 -0
  109. package/dist/design-tokens/design-token-presets.cjs +91 -0
  110. package/dist/design-tokens/design-token-presets.cjs.map +1 -0
  111. package/dist/design-tokens/design-token-presets.d.ts +34 -0
  112. package/dist/design-tokens/design-token-presets.d.ts.map +1 -0
  113. package/dist/design-tokens/design-token-presets.js +91 -0
  114. package/dist/design-tokens/design-token-presets.js.map +1 -0
  115. package/dist/design-tokens/design-token-types.d.ts +97 -0
  116. package/dist/design-tokens/design-token-types.d.ts.map +1 -0
  117. package/dist/design-tokens/index.cjs +10 -0
  118. package/dist/design-tokens/index.cjs.map +1 -0
  119. package/dist/design-tokens/index.d.ts +9 -0
  120. package/dist/design-tokens/index.d.ts.map +1 -0
  121. package/dist/design-tokens/index.js +10 -0
  122. package/dist/design-tokens/index.js.map +1 -0
  123. package/dist/dev-config.cjs +296 -0
  124. package/dist/dev-config.cjs.map +1 -0
  125. package/dist/dev-config.d.ts +238 -0
  126. package/dist/dev-config.d.ts.map +1 -0
  127. package/dist/dev-config.js +296 -0
  128. package/dist/dev-config.js.map +1 -0
  129. package/dist/effects.cjs +69 -0
  130. package/dist/effects.cjs.map +1 -0
  131. package/dist/effects.d.ts +152 -0
  132. package/dist/effects.d.ts.map +1 -0
  133. package/dist/effects.js +69 -0
  134. package/dist/effects.js.map +1 -0
  135. package/dist/global-registry.cjs +25 -0
  136. package/dist/global-registry.cjs.map +1 -0
  137. package/dist/global-registry.d.ts +19 -0
  138. package/dist/global-registry.d.ts.map +1 -0
  139. package/dist/global-registry.js +25 -0
  140. package/dist/global-registry.js.map +1 -0
  141. package/dist/hooks.cjs +378 -0
  142. package/dist/hooks.cjs.map +1 -0
  143. package/dist/hooks.d.ts +322 -0
  144. package/dist/hooks.d.ts.map +1 -0
  145. package/dist/hooks.js +378 -0
  146. package/dist/hooks.js.map +1 -0
  147. package/dist/host-adapter.d.ts +414 -0
  148. package/dist/host-adapter.d.ts.map +1 -0
  149. package/dist/index.cjs +229 -0
  150. package/dist/index.cjs.map +1 -0
  151. package/dist/index.d.ts +32 -0
  152. package/dist/index.d.ts.map +1 -0
  153. package/dist/index.js +226 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/jsx-dev-runtime.cjs +10 -0
  156. package/dist/jsx-dev-runtime.cjs.map +1 -0
  157. package/dist/jsx-dev-runtime.d.ts +5 -0
  158. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  159. package/dist/jsx-dev-runtime.js +11 -0
  160. package/dist/jsx-dev-runtime.js.map +1 -0
  161. package/dist/jsx-runtime.cjs +44 -0
  162. package/dist/jsx-runtime.cjs.map +1 -0
  163. package/dist/jsx-runtime.d.ts +24 -0
  164. package/dist/jsx-runtime.d.ts.map +1 -0
  165. package/dist/jsx-runtime.js +44 -0
  166. package/dist/jsx-runtime.js.map +1 -0
  167. package/dist/jsx-types.d.ts +25 -0
  168. package/dist/jsx-types.d.ts.map +1 -0
  169. package/dist/layout/appliers/container-applier.cjs +20 -0
  170. package/dist/layout/appliers/container-applier.cjs.map +1 -0
  171. package/dist/layout/appliers/container-applier.d.ts +9 -0
  172. package/dist/layout/appliers/container-applier.d.ts.map +1 -0
  173. package/dist/layout/appliers/container-applier.js +20 -0
  174. package/dist/layout/appliers/container-applier.js.map +1 -0
  175. package/dist/layout/appliers/position-applier.cjs +31 -0
  176. package/dist/layout/appliers/position-applier.cjs.map +1 -0
  177. package/dist/layout/appliers/position-applier.d.ts +8 -0
  178. package/dist/layout/appliers/position-applier.d.ts.map +1 -0
  179. package/dist/layout/appliers/position-applier.js +31 -0
  180. package/dist/layout/appliers/position-applier.js.map +1 -0
  181. package/dist/layout/layout-engine-test-utils.d.ts +26 -0
  182. package/dist/layout/layout-engine-test-utils.d.ts.map +1 -0
  183. package/dist/layout/layout-engine.cjs +628 -0
  184. package/dist/layout/layout-engine.cjs.map +1 -0
  185. package/dist/layout/layout-engine.d.ts +140 -0
  186. package/dist/layout/layout-engine.d.ts.map +1 -0
  187. package/dist/layout/layout-engine.js +628 -0
  188. package/dist/layout/layout-engine.js.map +1 -0
  189. package/dist/layout/strategies/base-strategy.cjs +31 -0
  190. package/dist/layout/strategies/base-strategy.cjs.map +1 -0
  191. package/dist/layout/strategies/base-strategy.d.ts +59 -0
  192. package/dist/layout/strategies/base-strategy.d.ts.map +1 -0
  193. package/dist/layout/strategies/base-strategy.js +31 -0
  194. package/dist/layout/strategies/base-strategy.js.map +1 -0
  195. package/dist/layout/strategies/column-layout.cjs +145 -0
  196. package/dist/layout/strategies/column-layout.cjs.map +1 -0
  197. package/dist/layout/strategies/column-layout.d.ts +38 -0
  198. package/dist/layout/strategies/column-layout.d.ts.map +1 -0
  199. package/dist/layout/strategies/column-layout.js +145 -0
  200. package/dist/layout/strategies/column-layout.js.map +1 -0
  201. package/dist/layout/strategies/row-layout.cjs +145 -0
  202. package/dist/layout/strategies/row-layout.cjs.map +1 -0
  203. package/dist/layout/strategies/row-layout.d.ts +38 -0
  204. package/dist/layout/strategies/row-layout.d.ts.map +1 -0
  205. package/dist/layout/strategies/row-layout.js +145 -0
  206. package/dist/layout/strategies/row-layout.js.map +1 -0
  207. package/dist/layout/strategies/stack-layout.cjs +94 -0
  208. package/dist/layout/strategies/stack-layout.cjs.map +1 -0
  209. package/dist/layout/strategies/stack-layout.d.ts +30 -0
  210. package/dist/layout/strategies/stack-layout.d.ts.map +1 -0
  211. package/dist/layout/strategies/stack-layout.js +94 -0
  212. package/dist/layout/strategies/stack-layout.js.map +1 -0
  213. package/dist/layout/types.d.ts +134 -0
  214. package/dist/layout/types.d.ts.map +1 -0
  215. package/dist/layout/utils/child-utils.cjs +129 -0
  216. package/dist/layout/utils/child-utils.cjs.map +1 -0
  217. package/dist/layout/utils/child-utils.d.ts +54 -0
  218. package/dist/layout/utils/child-utils.d.ts.map +1 -0
  219. package/dist/layout/utils/child-utils.js +129 -0
  220. package/dist/layout/utils/child-utils.js.map +1 -0
  221. package/dist/layout/utils/dimension-calculator.cjs +109 -0
  222. package/dist/layout/utils/dimension-calculator.cjs.map +1 -0
  223. package/dist/layout/utils/dimension-calculator.d.ts +59 -0
  224. package/dist/layout/utils/dimension-calculator.d.ts.map +1 -0
  225. package/dist/layout/utils/dimension-calculator.js +109 -0
  226. package/dist/layout/utils/dimension-calculator.js.map +1 -0
  227. package/dist/layout/utils/flex-distributor.cjs +173 -0
  228. package/dist/layout/utils/flex-distributor.cjs.map +1 -0
  229. package/dist/layout/utils/flex-distributor.d.ts +18 -0
  230. package/dist/layout/utils/flex-distributor.d.ts.map +1 -0
  231. package/dist/layout/utils/flex-distributor.js +173 -0
  232. package/dist/layout/utils/flex-distributor.js.map +1 -0
  233. package/dist/layout/utils/size-resolver.cjs +280 -0
  234. package/dist/layout/utils/size-resolver.cjs.map +1 -0
  235. package/dist/layout/utils/size-resolver.d.ts +84 -0
  236. package/dist/layout/utils/size-resolver.d.ts.map +1 -0
  237. package/dist/layout/utils/size-resolver.js +280 -0
  238. package/dist/layout/utils/size-resolver.js.map +1 -0
  239. package/dist/layout/utils/spacing-calculator.cjs +50 -0
  240. package/dist/layout/utils/spacing-calculator.cjs.map +1 -0
  241. package/dist/layout/utils/spacing-calculator.d.ts +27 -0
  242. package/dist/layout/utils/spacing-calculator.d.ts.map +1 -0
  243. package/dist/layout/utils/spacing-calculator.js +50 -0
  244. package/dist/layout/utils/spacing-calculator.js.map +1 -0
  245. package/dist/memo.cjs +18 -0
  246. package/dist/memo.cjs.map +1 -0
  247. package/dist/memo.d.ts +29 -0
  248. package/dist/memo.d.ts.map +1 -0
  249. package/dist/memo.js +18 -0
  250. package/dist/memo.js.map +1 -0
  251. package/dist/nineslice-contract.cjs +60 -0
  252. package/dist/nineslice-contract.cjs.map +1 -0
  253. package/dist/nineslice-contract.d.ts +107 -0
  254. package/dist/nineslice-contract.d.ts.map +1 -0
  255. package/dist/nineslice-contract.js +60 -0
  256. package/dist/nineslice-contract.js.map +1 -0
  257. package/dist/placeholder.cjs +12 -0
  258. package/dist/placeholder.cjs.map +1 -0
  259. package/dist/placeholder.d.ts +44 -0
  260. package/dist/placeholder.d.ts.map +1 -0
  261. package/dist/placeholder.js +12 -0
  262. package/dist/placeholder.js.map +1 -0
  263. package/dist/portal.cjs +89 -0
  264. package/dist/portal.cjs.map +1 -0
  265. package/dist/portal.d.ts +62 -0
  266. package/dist/portal.d.ts.map +1 -0
  267. package/dist/portal.js +89 -0
  268. package/dist/portal.js.map +1 -0
  269. package/dist/primitive-contracts.cjs +12 -0
  270. package/dist/primitive-contracts.cjs.map +1 -0
  271. package/dist/primitive-contracts.d.ts +186 -0
  272. package/dist/primitive-contracts.d.ts.map +1 -0
  273. package/dist/primitive-contracts.js +12 -0
  274. package/dist/primitive-contracts.js.map +1 -0
  275. package/dist/theme.cjs +332 -0
  276. package/dist/theme.cjs.map +1 -0
  277. package/dist/theme.d.ts +204 -0
  278. package/dist/theme.d.ts.map +1 -0
  279. package/dist/theme.js +332 -0
  280. package/dist/theme.js.map +1 -0
  281. package/dist/types.d.ts +86 -0
  282. package/dist/types.d.ts.map +1 -0
  283. package/dist/vdom/create-runtime.cjs +79 -0
  284. package/dist/vdom/create-runtime.cjs.map +1 -0
  285. package/dist/vdom/create-runtime.d.ts +7 -0
  286. package/dist/vdom/create-runtime.d.ts.map +1 -0
  287. package/dist/vdom/create-runtime.js +79 -0
  288. package/dist/vdom/create-runtime.js.map +1 -0
  289. package/dist/vdom/index.cjs +8 -0
  290. package/dist/vdom/index.cjs.map +1 -0
  291. package/dist/vdom/index.d.ts +4 -0
  292. package/dist/vdom/index.d.ts.map +1 -0
  293. package/dist/vdom/index.js +8 -0
  294. package/dist/vdom/index.js.map +1 -0
  295. package/dist/vdom/mount.cjs +161 -0
  296. package/dist/vdom/mount.cjs.map +1 -0
  297. package/dist/vdom/mount.d.ts +6 -0
  298. package/dist/vdom/mount.d.ts.map +1 -0
  299. package/dist/vdom/mount.js +161 -0
  300. package/dist/vdom/mount.js.map +1 -0
  301. package/dist/vdom/patch.cjs +163 -0
  302. package/dist/vdom/patch.cjs.map +1 -0
  303. package/dist/vdom/patch.d.ts +3 -0
  304. package/dist/vdom/patch.d.ts.map +1 -0
  305. package/dist/vdom/patch.js +163 -0
  306. package/dist/vdom/patch.js.map +1 -0
  307. package/dist/vdom/registry.cjs +85 -0
  308. package/dist/vdom/registry.cjs.map +1 -0
  309. package/dist/vdom/registry.d.ts +28 -0
  310. package/dist/vdom/registry.d.ts.map +1 -0
  311. package/dist/vdom/registry.js +85 -0
  312. package/dist/vdom/registry.js.map +1 -0
  313. package/dist/vdom/runtime-helpers.cjs +23 -0
  314. package/dist/vdom/runtime-helpers.cjs.map +1 -0
  315. package/dist/vdom/runtime-helpers.d.ts +8 -0
  316. package/dist/vdom/runtime-helpers.d.ts.map +1 -0
  317. package/dist/vdom/runtime-helpers.js +23 -0
  318. package/dist/vdom/runtime-helpers.js.map +1 -0
  319. package/dist/vdom/surface.cjs +107 -0
  320. package/dist/vdom/surface.cjs.map +1 -0
  321. package/dist/vdom/surface.d.ts +9 -0
  322. package/dist/vdom/surface.d.ts.map +1 -0
  323. package/dist/vdom/surface.js +107 -0
  324. package/dist/vdom/surface.js.map +1 -0
  325. package/dist/vdom/types.d.ts +104 -0
  326. package/dist/vdom/types.d.ts.map +1 -0
  327. package/dist/vdom/utils.cjs +146 -0
  328. package/dist/vdom/utils.cjs.map +1 -0
  329. package/dist/vdom/utils.d.ts +24 -0
  330. package/dist/vdom/utils.d.ts.map +1 -0
  331. package/dist/vdom/utils.js +146 -0
  332. package/dist/vdom/utils.js.map +1 -0
  333. package/dist/vdom.d.ts +4 -0
  334. package/dist/vdom.d.ts.map +1 -0
  335. package/dist/vector-draw-context.d.ts +63 -0
  336. package/dist/vector-draw-context.d.ts.map +1 -0
  337. package/package.json +161 -0
  338. package/vdom/index.cjs +1 -0
  339. package/vdom/index.d.ts +1 -0
  340. package/vdom/index.js +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"border-geometry.cjs","sources":["../src/border-geometry.ts"],"sourcesContent":["/**\n * Border Geometry — centralized, renderer-neutral border rendering algorithm.\n *\n * This module provides the **single source of truth** for rendering complex\n * borders (asymmetric, dashed, dotted, rounded) across ALL renderers.\n *\n * ## Architecture\n *\n * - **Core** owns the geometry algorithm via {@link drawBorderGeometry}.\n * - **Renderers** only translate the calls to their native draw API via\n * the existing {@link VectorDrawContext} interface.\n * - Renderers decide *when* to use the core fallback via\n * {@link shouldUseCoreBorderGeometry}.\n *\n * ## Dotted Border Definition\n *\n * `dotted` is defined centrally as a sequence of **real round filled circles**\n * placed along the border mid-line. `dash[0]` controls the gap and\n * `dash[1]` optionally overrides the dot diameter.\n *\n * ## Mandatory Core Fallback\n *\n * Any **asymmetric** border (per-side widths not all equal) MUST use the\n * core geometry algorithm. Renderers MUST NOT contain their own asymmetric\n * border rendering logic.\n *\n * ## Optional Core Fallback\n *\n * A renderer may also route **symmetric** cases through the core fallback\n * when its native path produces visibly poor results.\n *\n * ## Legacy Border\n *\n * The legacy `borderWidth`/`borderColor`/`borderAlpha` props are **not**\n * affected — they continue to use renderer-native drawing.\n */\n\nimport type { BorderPropsV2, BorderSideInsets } from './core-props'\nimport type { VectorDrawContext } from './vector-draw-context'\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a BorderPropsV2 width to per-side pixel values.\n * A plain `number` is applied uniformly; an object allows per-side control.\n */\nexport function resolveBorderSides(width: number | BorderSideInsets<number> | undefined): {\n top: number\n right: number\n bottom: number\n left: number\n} {\n if (width === undefined) return { top: 0, right: 0, bottom: 0, left: 0 }\n if (typeof width === 'number') {\n const w = Math.max(0, width)\n return { top: w, right: w, bottom: w, left: w }\n }\n return {\n top: Math.max(0, width.top ?? 0),\n right: Math.max(0, width.right ?? 0),\n bottom: Math.max(0, width.bottom ?? 0),\n left: Math.max(0, width.left ?? 0),\n }\n}\n\n/** Check whether all four side widths are identical. */\nexport function isUniformBorder(sides: {\n top: number\n right: number\n bottom: number\n left: number\n}): boolean {\n return sides.top === sides.right && sides.right === sides.bottom && sides.bottom === sides.left\n}\n\n/**\n * Resolve the per-corner radii to a normalized object form.\n */\nexport function resolveCornerRadii(\n cr: number | { tl?: number; tr?: number; bl?: number; br?: number } | undefined\n): { tl: number; tr: number; bl: number; br: number } {\n if (typeof cr === 'number') {\n const r = Math.max(0, cr)\n return { tl: r, tr: r, bl: r, br: r }\n }\n if (cr) {\n return {\n tl: Math.max(0, cr.tl ?? 0),\n tr: Math.max(0, cr.tr ?? 0),\n bl: Math.max(0, cr.bl ?? 0),\n br: Math.max(0, cr.br ?? 0),\n }\n }\n return { tl: 0, tr: 0, bl: 0, br: 0 }\n}\n\n/** Check whether any corner has a non-zero radius. */\nexport function hasAnyCornerRadius(corners: {\n tl: number\n tr: number\n bl: number\n br: number\n}): boolean {\n return corners.tl > 0 || corners.tr > 0 || corners.bl > 0 || corners.br > 0\n}\n\n// ---------------------------------------------------------------------------\n// Fallback decision\n// ---------------------------------------------------------------------------\n\n/**\n * Known renderer issues that can trigger the core fallback for otherwise\n * symmetric borders.\n */\nexport type RendererIssue =\n | 'rounded-dotted' // rounded corners + dotted style → poor native rendering\n | 'rounded-dashed-cap' // rounded + dashed + cap not supported natively\n | 'all' // route everything through core\n\n/**\n * Determine whether the core border geometry fallback should be used.\n *\n * **Mandatory:** Any asymmetric border (per-side widths differ).\n * **Optional:** Renderer can declare known issues to force the fallback\n * even for symmetric borders.\n *\n * @param border - The border configuration\n * @param rendererIssues - Known renderer-specific issues (optional)\n * @returns `true` if the core fallback should be used\n */\nexport function shouldUseCoreBorderGeometry(\n border: Pick<BorderPropsV2, 'width' | 'style'>,\n rendererIssues?: RendererIssue[]\n): boolean {\n const sides = resolveBorderSides(border.width)\n const asymmetric = !isUniformBorder(sides)\n\n if (asymmetric) return true\n\n if (rendererIssues && rendererIssues.length > 0) {\n if (rendererIssues.includes('all')) return true\n if (rendererIssues.includes('rounded-dotted') && border.style === 'dotted') {\n return true\n }\n if (rendererIssues.includes('rounded-dashed-cap') && border.style === 'dashed') {\n return true\n }\n }\n\n return false\n}\n\n// ---------------------------------------------------------------------------\n// Segment types (internal)\n// ---------------------------------------------------------------------------\n\ntype PerimeterPoint = Point & { width: number }\n\ntype PerimeterSegment = {\n x1: number\n y1: number\n x2: number\n y2: number\n width1: number\n width2: number\n length: number\n}\n\n// ---------------------------------------------------------------------------\n// Perimeter builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build the ordered list of sampled points for the border mid-line.\n *\n * The mid-line position depends on {@link BorderPropsV2.align}:\n * - `inside`: mid-line at +halfWidth from box edge (border fully inside)\n * - `center`: mid-line at the box edge (border centered on edge)\n * - `outside`: mid-line at -halfWidth from box edge (border fully outside)\n */\nfunction pushPerimeterPoint(points: PerimeterPoint[], pt: Point, width: number): void {\n const last = points[points.length - 1]\n if (!last || Math.abs(last.x - pt.x) > 0.001 || Math.abs(last.y - pt.y) > 0.001) {\n points.push({ x: pt.x, y: pt.y, width })\n return\n }\n last.width = width\n}\n\nfunction appendPerimeterArcPoints(\n points: PerimeterPoint[],\n corner: CornerEllipse,\n startAngle: number,\n endAngle: number,\n widthStart: number,\n widthEnd: number\n): void {\n const start = pointOnEllipse(corner, startAngle)\n pushPerimeterPoint(points, start, widthStart)\n\n if (corner.rx <= 0 || corner.ry <= 0) {\n pushPerimeterPoint(points, pointOnEllipse(corner, endAngle), widthEnd)\n return\n }\n\n const span = endAngle - startAngle\n const maxR = Math.max(corner.rx, corner.ry)\n const steps = Math.max(1, Math.min(24, Math.ceil((Math.abs(span) * maxR) / 8)))\n for (let i = 1; i <= steps; i++) {\n const t = i / steps\n const angle = startAngle + span * t\n const width = widthStart + (widthEnd - widthStart) * t\n pushPerimeterPoint(points, pointOnEllipse(corner, angle), width)\n }\n}\n\nfunction buildPerimeterPoints(\n w: number,\n h: number,\n sides: { top: number; right: number; bottom: number; left: number },\n corners: { tl: number; tr: number; bl: number; br: number },\n align: 'inside' | 'center' | 'outside'\n): PerimeterPoint[] {\n const offsets = resolveBorderOffsets(sides, align)\n const outer = buildOuterContour(w, h, corners, offsets.outer)\n const inner = buildInnerContour(w, h, corners, offsets.inner)\n const mid = averageContours(outer, inner)\n const points: PerimeterPoint[] = []\n\n pushPerimeterPoint(points, { x: mid.tl.cx, y: mid.top }, sides.top)\n pushPerimeterPoint(points, { x: mid.tr.cx, y: mid.top }, sides.top)\n appendPerimeterArcPoints(points, mid.tr, -Math.PI / 2, 0, sides.top, sides.right)\n pushPerimeterPoint(points, { x: mid.right, y: mid.br.cy }, sides.right)\n appendPerimeterArcPoints(points, mid.br, 0, Math.PI / 2, sides.right, sides.bottom)\n pushPerimeterPoint(points, { x: mid.bl.cx, y: mid.bottom }, sides.bottom)\n appendPerimeterArcPoints(points, mid.bl, Math.PI / 2, Math.PI, sides.bottom, sides.left)\n pushPerimeterPoint(points, { x: mid.left, y: mid.tl.cy }, sides.left)\n appendPerimeterArcPoints(points, mid.tl, Math.PI, Math.PI * 1.5, sides.left, sides.top)\n\n if (points.length > 1) {\n const first = points[0] ?? { x: 0, y: 0, width: 0 }\n const last = points[points.length - 1] ?? { x: 0, y: 0, width: 0 }\n if (Math.abs(first.x - last.x) <= 0.001 && Math.abs(first.y - last.y) <= 0.001) {\n points.pop()\n }\n }\n\n return points\n}\n\nfunction buildPerimeterSegments(points: PerimeterPoint[]): PerimeterSegment[] {\n if (points.length < 2) return []\n\n const segs: PerimeterSegment[] = []\n for (let i = 0; i < points.length; i++) {\n const p1 = points[i] ?? { x: 0, y: 0, width: 0 }\n const p2 = points[(i + 1) % points.length] ?? { x: 0, y: 0, width: 0 }\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n const length = Math.sqrt(dx * dx + dy * dy)\n if (length <= 0.001) continue\n segs.push({\n x1: p1.x,\n y1: p1.y,\n x2: p2.x,\n y2: p2.y,\n width1: p1.width,\n width2: p2.width,\n length,\n })\n }\n return segs\n}\n\n/** Get the point and interpolated width at a given distance along a perimeter segment. */\nfunction pointAtDistance(\n seg: PerimeterSegment,\n t: number\n): { x: number; y: number; width: number } {\n const frac = seg.length > 0 ? t / seg.length : 0\n return {\n x: seg.x1 + (seg.x2 - seg.x1) * frac,\n y: seg.y1 + (seg.y2 - seg.y1) * frac,\n width: seg.width1 + (seg.width2 - seg.width1) * frac,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Solid border drawing\n// ---------------------------------------------------------------------------\n\ntype Point = { x: number; y: number }\n\ntype CornerEllipse = {\n cx: number\n cy: number\n rx: number\n ry: number\n}\n\ntype RoundedContour = {\n left: number\n top: number\n right: number\n bottom: number\n tl: CornerEllipse\n tr: CornerEllipse\n br: CornerEllipse\n bl: CornerEllipse\n}\n\ntype BorderOffsets = {\n outer: { top: number; right: number; bottom: number; left: number }\n inner: { top: number; right: number; bottom: number; left: number }\n}\n\nfunction resolveBorderOffsets(\n sides: { top: number; right: number; bottom: number; left: number },\n align: 'inside' | 'center' | 'outside'\n): BorderOffsets {\n if (align === 'inside') {\n return {\n outer: { top: 0, right: 0, bottom: 0, left: 0 },\n inner: { ...sides },\n }\n }\n if (align === 'outside') {\n return {\n outer: { ...sides },\n inner: { top: 0, right: 0, bottom: 0, left: 0 },\n }\n }\n return {\n outer: {\n top: sides.top / 2,\n right: sides.right / 2,\n bottom: sides.bottom / 2,\n left: sides.left / 2,\n },\n inner: {\n top: sides.top / 2,\n right: sides.right / 2,\n bottom: sides.bottom / 2,\n left: sides.left / 2,\n },\n }\n}\n\nfunction buildOuterContour(\n w: number,\n h: number,\n corners: { tl: number; tr: number; bl: number; br: number },\n offsets: BorderOffsets['outer']\n): RoundedContour {\n const left = -offsets.left\n const top = -offsets.top\n const right = w + offsets.right\n const bottom = h + offsets.bottom\n return {\n left,\n top,\n right,\n bottom,\n tl: {\n cx: corners.tl,\n cy: corners.tl,\n rx: corners.tl + offsets.left,\n ry: corners.tl + offsets.top,\n },\n tr: {\n cx: w - corners.tr,\n cy: corners.tr,\n rx: corners.tr + offsets.right,\n ry: corners.tr + offsets.top,\n },\n br: {\n cx: w - corners.br,\n cy: h - corners.br,\n rx: corners.br + offsets.right,\n ry: corners.br + offsets.bottom,\n },\n bl: {\n cx: corners.bl,\n cy: h - corners.bl,\n rx: corners.bl + offsets.left,\n ry: corners.bl + offsets.bottom,\n },\n }\n}\n\nfunction buildInnerContour(\n w: number,\n h: number,\n corners: { tl: number; tr: number; bl: number; br: number },\n offsets: BorderOffsets['inner']\n): RoundedContour {\n const left = offsets.left\n const top = offsets.top\n const right = w - offsets.right\n const bottom = h - offsets.bottom\n\n const tlRx = Math.max(0, corners.tl - offsets.left)\n const tlRy = Math.max(0, corners.tl - offsets.top)\n const trRx = Math.max(0, corners.tr - offsets.right)\n const trRy = Math.max(0, corners.tr - offsets.top)\n const brRx = Math.max(0, corners.br - offsets.right)\n const brRy = Math.max(0, corners.br - offsets.bottom)\n const blRx = Math.max(0, corners.bl - offsets.left)\n const blRy = Math.max(0, corners.bl - offsets.bottom)\n\n return {\n left,\n top,\n right,\n bottom,\n tl: { cx: left + tlRx, cy: top + tlRy, rx: tlRx, ry: tlRy },\n tr: { cx: right - trRx, cy: top + trRy, rx: trRx, ry: trRy },\n br: { cx: right - brRx, cy: bottom - brRy, rx: brRx, ry: brRy },\n bl: { cx: left + blRx, cy: bottom - blRy, rx: blRx, ry: blRy },\n }\n}\n\nfunction averageContours(a: RoundedContour, b: RoundedContour): RoundedContour {\n const avgCorner = (\n ca: CornerEllipse,\n cb: CornerEllipse,\n sideX: number,\n sideY: number,\n right = false,\n bottom = false\n ): CornerEllipse => {\n const rx = (ca.rx + cb.rx) / 2\n const ry = (ca.ry + cb.ry) / 2\n return {\n cx: right ? sideX - rx : sideX + rx,\n cy: bottom ? sideY - ry : sideY + ry,\n rx,\n ry,\n }\n }\n\n return {\n left: (a.left + b.left) / 2,\n top: (a.top + b.top) / 2,\n right: (a.right + b.right) / 2,\n bottom: (a.bottom + b.bottom) / 2,\n tl: avgCorner(a.tl, b.tl, (a.left + b.left) / 2, (a.top + b.top) / 2),\n tr: avgCorner(a.tr, b.tr, (a.right + b.right) / 2, (a.top + b.top) / 2, true, false),\n br: avgCorner(a.br, b.br, (a.right + b.right) / 2, (a.bottom + b.bottom) / 2, true, true),\n bl: avgCorner(a.bl, b.bl, (a.left + b.left) / 2, (a.bottom + b.bottom) / 2, false, true),\n }\n}\n\nfunction pointOnEllipse(corner: CornerEllipse, angle: number): Point {\n return {\n x: corner.cx + corner.rx * Math.cos(angle),\n y: corner.cy + corner.ry * Math.sin(angle),\n }\n}\n\nfunction pushPoint(points: Point[], pt: Point): void {\n const last = points[points.length - 1]\n if (!last || Math.abs(last.x - pt.x) > 0.001 || Math.abs(last.y - pt.y) > 0.001) {\n points.push(pt)\n }\n}\n\nfunction appendEllipseArcPoints(\n points: Point[],\n corner: CornerEllipse,\n startAngle: number,\n endAngle: number\n): void {\n const start = pointOnEllipse(corner, startAngle)\n const end = pointOnEllipse(corner, endAngle)\n pushPoint(points, start)\n\n if (corner.rx <= 0 || corner.ry <= 0) {\n pushPoint(points, end)\n return\n }\n\n const span = endAngle - startAngle\n const maxR = Math.max(corner.rx, corner.ry)\n const steps = Math.max(1, Math.min(24, Math.ceil((Math.abs(span) * maxR) / 8)))\n for (let i = 1; i <= steps; i++) {\n const t = i / steps\n const angle = startAngle + span * t\n pushPoint(points, pointOnEllipse(corner, angle))\n }\n}\n\nfunction buildContourPoints(contour: RoundedContour): Point[] {\n const points: Point[] = []\n pushPoint(points, { x: contour.tl.cx, y: contour.top })\n pushPoint(points, { x: contour.tr.cx, y: contour.top })\n appendEllipseArcPoints(points, contour.tr, -Math.PI / 2, 0)\n pushPoint(points, { x: contour.right, y: contour.br.cy })\n appendEllipseArcPoints(points, contour.br, 0, Math.PI / 2)\n pushPoint(points, { x: contour.bl.cx, y: contour.bottom })\n appendEllipseArcPoints(points, contour.bl, Math.PI / 2, Math.PI)\n pushPoint(points, { x: contour.left, y: contour.tl.cy })\n appendEllipseArcPoints(points, contour.tl, Math.PI, Math.PI * 1.5)\n return points\n}\n\nfunction traceClosedPath(ctx: VectorDrawContext, points: Point[]): void {\n if (points.length === 0) return\n if (points[0] === undefined) return\n ctx.moveTo(points[0].x, points[0].y)\n for (let i = 1; i < points.length; i++) {\n const pt = points[i] ?? { x: 0, y: 0 }\n ctx.lineTo(pt.x, pt.y)\n }\n ctx.closePath()\n}\n\n/**\n * Draw a solid border as the filled ring between outer and inner contours.\n * This fixes the previous `edge strips + corner patches` model, which\n * broke down for asymmetric widths combined with rounded corners.\n */\nfunction drawSolidBorder(\n ctx: VectorDrawContext,\n w: number,\n h: number,\n sides: { top: number; right: number; bottom: number; left: number },\n corners: { tl: number; tr: number; bl: number; br: number },\n color: number,\n alpha: number,\n align: 'inside' | 'center' | 'outside'\n): void {\n const offsets = resolveBorderOffsets(sides, align)\n const outer = buildOuterContour(w, h, corners, offsets.outer)\n const inner = buildInnerContour(w, h, corners, offsets.inner)\n const outerPoints = buildContourPoints(outer)\n const innerPoints = buildContourPoints(inner)\n\n if (outerPoints.length < 3) return\n\n ctx.fillStyle(color, alpha)\n ctx.beginPath()\n traceClosedPath(ctx, outerPoints)\n traceClosedPath(ctx, [...innerPoints].reverse())\n ctx.fillPath()\n}\n\n// ---------------------------------------------------------------------------\n// Dashed border drawing\n// ---------------------------------------------------------------------------\n\n/**\n * Draw a dashed border by walking a continuous closed perimeter polyline\n * and stroking each dash chunk as a single path. This avoids re-starting\n * short line segments at rounded corners, which previously produced\n * visible spikes and broken joins.\n */\nfunction appendDashPoint(points: Point[], pt: Point): void {\n const last = points[points.length - 1]\n if (!last || Math.abs(last.x - pt.x) > 0.001 || Math.abs(last.y - pt.y) > 0.001) {\n points.push(pt)\n }\n}\n\nfunction strokeDashedPath(\n ctx: VectorDrawContext,\n points: Point[],\n widths: number[],\n color: number,\n alpha: number\n): void {\n if (points.length < 2 || widths.length === 0) return\n const width = widths.reduce((sum, value) => sum + value, 0) / widths.length\n if (width <= 0) return\n\n ctx.lineStyle(width, color, alpha)\n ctx.beginPath()\n if (points[0] === undefined) return\n ctx.moveTo(points[0].x, points[0].y)\n for (let i = 1; i < points.length; i++) {\n const pt = points[i]\n if (pt === undefined) continue\n ctx.lineTo(pt.x, pt.y)\n }\n ctx.strokePath()\n}\n\nfunction drawDashedBorder(\n ctx: VectorDrawContext,\n w: number,\n h: number,\n sides: { top: number; right: number; bottom: number; left: number },\n corners: { tl: number; tr: number; bl: number; br: number },\n border: BorderPropsV2,\n color: number,\n alpha: number,\n align: 'inside' | 'center' | 'outside'\n): void {\n const segs = buildPerimeterSegments(buildPerimeterPoints(w, h, sides, corners, align))\n if (segs.length === 0) return\n\n const maxWidth = Math.max(sides.top, sides.right, sides.bottom, sides.left)\n const dashArray = border.dash ?? [maxWidth * 3, maxWidth * 2]\n const dashOffset = border.dashOffset ?? 0\n\n const pattern = dashArray.length % 2 === 0 ? dashArray : [...dashArray, ...dashArray]\n const patternSum = pattern.reduce((a, b) => a + b, 0)\n if (patternSum <= 0) return\n\n let patIdx = 0\n let drawing = true\n let accumulated = pattern[0] ?? 0\n let offset = dashOffset % patternSum\n if (offset < 0) offset += patternSum\n while (offset > 0.001) {\n const consume = Math.min(offset, accumulated)\n offset -= consume\n accumulated -= consume\n if (accumulated <= 0.001) {\n patIdx = (patIdx + 1) % pattern.length\n drawing = !drawing\n accumulated = pattern[patIdx] ?? 0\n }\n }\n\n let dashPoints: Point[] = []\n let dashWidths: number[] = []\n\n const flushDash = (): void => {\n if (dashPoints.length > 1) {\n strokeDashedPath(ctx, dashPoints, dashWidths, color, alpha)\n }\n dashPoints = []\n dashWidths = []\n }\n\n for (const seg of segs) {\n const sLen = seg.length\n if (sLen <= 0) continue\n\n let t = 0\n while (t < sLen) {\n const consume = Math.min(accumulated, sLen - t)\n const end = t + consume\n\n if (drawing && consume > 0) {\n const p1 = pointAtDistance(seg, t)\n const p2 = pointAtDistance(seg, end)\n if (dashPoints.length === 0) {\n appendDashPoint(dashPoints, p1)\n dashWidths.push(p1.width)\n }\n appendDashPoint(dashPoints, p2)\n dashWidths.push((p1.width + p2.width) / 2)\n }\n\n t += consume\n accumulated -= consume\n\n if (accumulated <= 0.001) {\n if (drawing) flushDash()\n patIdx = (patIdx + 1) % pattern.length\n drawing = !drawing\n accumulated = pattern[patIdx] ?? 0\n }\n }\n }\n\n if (drawing) flushDash()\n}\n\n// ---------------------------------------------------------------------------\n// Dotted border drawing — real round circles along the mid-line\n// ---------------------------------------------------------------------------\n\n/**\n * Draw a dotted border as a sequence of **real round filled circles**\n * placed along the border mid-line. Uses self-contained\n * {@link VectorDrawContext.fillCircleStyled} calls.\n *\n * ## Dot Geometry\n *\n * - **Dot diameter**: `dash[1]` if `dash` has ≥2 elements, otherwise `borderWidth` (per edge)\n * - **Dot gap** (edge-to-edge): `dash[0]` if `dash` has ≥1 element, otherwise `borderWidth`\n * - **Step** (center-to-center) = dotDiameter + gap\n *\n * Single-element `dash: [gap]` sets only the gap — dot diameter follows the\n * per-edge border width. This is the recommended form for asymmetric borders.\n *\n * Two-element `dash: [gap, size]` sets both gap and dot-diameter override.\n * (Yes, gap first — the common use-case is spacing control.)\n */\nfunction drawDottedBorder(\n ctx: VectorDrawContext,\n w: number,\n h: number,\n sides: { top: number; right: number; bottom: number; left: number },\n corners: { tl: number; tr: number; bl: number; br: number },\n border: BorderPropsV2,\n color: number,\n alpha: number,\n align: 'inside' | 'center' | 'outside'\n): void {\n const segs = buildPerimeterSegments(buildPerimeterPoints(w, h, sides, corners, align))\n if (segs.length === 0) return\n\n // dash[0] = gap, dash[1] = dot-diameter override (both optional)\n const dotGap = border.dash?.[0] ?? Math.max(sides.top, sides.right, sides.bottom, sides.left)\n const dotDiameterOverride: number | undefined = border.dash?.[1]\n\n const totalLength = segs.reduce((sum, seg) => sum + seg.length, 0)\n if (totalLength <= 0) return\n\n const fallbackDiameter = Math.max(sides.top, sides.right, sides.bottom, sides.left)\n const baseDiameter = dotDiameterOverride ?? fallbackDiameter\n const step = baseDiameter + dotGap\n if (step <= 0) return\n\n let distance = step / 2 + (border.dashOffset ?? 0)\n while (distance < 0) distance += step\n\n for (; distance < totalLength; distance += step) {\n let remaining = distance\n for (const seg of segs) {\n if (remaining <= seg.length) {\n const pt = pointAtDistance(seg, remaining)\n const dotDiameter = dotDiameterOverride ?? pt.width\n const dotRadius = dotDiameter / 2\n if (dotRadius > 0) {\n ctx.fillCircleStyled(pt.x, pt.y, dotRadius, color, alpha)\n }\n break\n }\n remaining -= seg.length\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Input geometry for border drawing.\n */\nexport interface BorderGeometryInput {\n /** Box dimensions */\n box: { x: number; y: number; w: number; h: number }\n /** Per-side border widths */\n sides: { top: number; right: number; bottom: number; left: number }\n /** Per-corner radii */\n corners: { tl: number; tr: number; bl: number; br: number }\n}\n\n/**\n * Draw a border using the centralized core geometry algorithm.\n *\n * This is the **single source of truth** for all complex border rendering.\n * It handles solid, dashed, and dotted styles, asymmetric widths, and\n * rounded corners.\n *\n * The function draws onto any {@link VectorDrawContext} — renderers only\n * need to wrap their native Graphics object in a VectorDrawContext adapter\n * and call this function.\n *\n * ## Dotted Definition\n *\n * `dotted` borders are rendered as real round filled circles (via\n * {@link VectorDrawContext.fillCircle}) placed along the border mid-line.\n * `dash[0]` controls the gap and `dash[1]` optionally overrides the\n * dot diameter.\n *\n * ## Align\n *\n * `border.align` adjusts where the border sits relative to the box edge:\n * - `center` (default): half inside, half outside\n * - `inside`: fully inside the box\n * - `outside`: fully outside the box\n *\n * @param ctx - Renderer-neutral draw context\n * @param input - Box geometry and border parameters\n * @param border - Border style configuration\n */\nexport function drawBorderGeometry(\n ctx: VectorDrawContext,\n input: BorderGeometryInput,\n border: BorderPropsV2\n): void {\n const { box, sides, corners } = input\n const { w, h } = box\n const color = border.color ?? 0xffffff\n const alpha = typeof border.alpha === 'number' ? border.alpha : 1\n const maxSw = Math.max(sides.top, sides.right, sides.bottom, sides.left)\n\n if (maxSw <= 0) return\n if (w <= 0 || h <= 0) return\n\n const align = border.align ?? 'center'\n const style = border.style ?? 'solid'\n\n switch (style) {\n case 'dotted':\n drawDottedBorder(ctx, w, h, sides, corners, border, color, alpha, align)\n break\n case 'dashed':\n drawDashedBorder(ctx, w, h, sides, corners, border, color, alpha, align)\n break\n case 'solid':\n default:\n drawSolidBorder(ctx, w, h, sides, corners, color, alpha, align)\n break\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { BorderPropsV2, BorderSideInsets } from './core-props';
2
+ import { VectorDrawContext } from './vector-draw-context';
3
+ /**
4
+ * Resolve a BorderPropsV2 width to per-side pixel values.
5
+ * A plain `number` is applied uniformly; an object allows per-side control.
6
+ */
7
+ export declare function resolveBorderSides(width: number | BorderSideInsets<number> | undefined): {
8
+ top: number;
9
+ right: number;
10
+ bottom: number;
11
+ left: number;
12
+ };
13
+ /** Check whether all four side widths are identical. */
14
+ export declare function isUniformBorder(sides: {
15
+ top: number;
16
+ right: number;
17
+ bottom: number;
18
+ left: number;
19
+ }): boolean;
20
+ /**
21
+ * Resolve the per-corner radii to a normalized object form.
22
+ */
23
+ export declare function resolveCornerRadii(cr: number | {
24
+ tl?: number;
25
+ tr?: number;
26
+ bl?: number;
27
+ br?: number;
28
+ } | undefined): {
29
+ tl: number;
30
+ tr: number;
31
+ bl: number;
32
+ br: number;
33
+ };
34
+ /** Check whether any corner has a non-zero radius. */
35
+ export declare function hasAnyCornerRadius(corners: {
36
+ tl: number;
37
+ tr: number;
38
+ bl: number;
39
+ br: number;
40
+ }): boolean;
41
+ /**
42
+ * Known renderer issues that can trigger the core fallback for otherwise
43
+ * symmetric borders.
44
+ */
45
+ export type RendererIssue = 'rounded-dotted' | 'rounded-dashed-cap' | 'all';
46
+ /**
47
+ * Determine whether the core border geometry fallback should be used.
48
+ *
49
+ * **Mandatory:** Any asymmetric border (per-side widths differ).
50
+ * **Optional:** Renderer can declare known issues to force the fallback
51
+ * even for symmetric borders.
52
+ *
53
+ * @param border - The border configuration
54
+ * @param rendererIssues - Known renderer-specific issues (optional)
55
+ * @returns `true` if the core fallback should be used
56
+ */
57
+ export declare function shouldUseCoreBorderGeometry(border: Pick<BorderPropsV2, 'width' | 'style'>, rendererIssues?: RendererIssue[]): boolean;
58
+ /**
59
+ * Input geometry for border drawing.
60
+ */
61
+ export interface BorderGeometryInput {
62
+ /** Box dimensions */
63
+ box: {
64
+ x: number;
65
+ y: number;
66
+ w: number;
67
+ h: number;
68
+ };
69
+ /** Per-side border widths */
70
+ sides: {
71
+ top: number;
72
+ right: number;
73
+ bottom: number;
74
+ left: number;
75
+ };
76
+ /** Per-corner radii */
77
+ corners: {
78
+ tl: number;
79
+ tr: number;
80
+ bl: number;
81
+ br: number;
82
+ };
83
+ }
84
+ /**
85
+ * Draw a border using the centralized core geometry algorithm.
86
+ *
87
+ * This is the **single source of truth** for all complex border rendering.
88
+ * It handles solid, dashed, and dotted styles, asymmetric widths, and
89
+ * rounded corners.
90
+ *
91
+ * The function draws onto any {@link VectorDrawContext} — renderers only
92
+ * need to wrap their native Graphics object in a VectorDrawContext adapter
93
+ * and call this function.
94
+ *
95
+ * ## Dotted Definition
96
+ *
97
+ * `dotted` borders are rendered as real round filled circles (via
98
+ * {@link VectorDrawContext.fillCircle}) placed along the border mid-line.
99
+ * `dash[0]` controls the gap and `dash[1]` optionally overrides the
100
+ * dot diameter.
101
+ *
102
+ * ## Align
103
+ *
104
+ * `border.align` adjusts where the border sits relative to the box edge:
105
+ * - `center` (default): half inside, half outside
106
+ * - `inside`: fully inside the box
107
+ * - `outside`: fully outside the box
108
+ *
109
+ * @param ctx - Renderer-neutral draw context
110
+ * @param input - Box geometry and border parameters
111
+ * @param border - Border style configuration
112
+ */
113
+ export declare function drawBorderGeometry(ctx: VectorDrawContext, input: BorderGeometryInput, border: BorderPropsV2): void;
114
+ //# sourceMappingURL=border-geometry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"border-geometry.d.ts","sourceRoot":"","sources":["../src/border-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAM9D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG;IACxF,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAYA;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAEV;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAC9E;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAcpD;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX,GAAG,OAAO,CAEV;AAMD;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,oBAAoB,GACpB,KAAK,CAAA;AAET;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,EAC9C,cAAc,CAAC,EAAE,aAAa,EAAE,GAC/B,OAAO,CAiBT;AAglBD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qBAAqB;IACrB,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACnD,6BAA6B;IAC7B,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACnE,uBAAuB;IACvB,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,EAC1B,MAAM,EAAE,aAAa,GACpB,IAAI,CAyBN"}
@@ -0,0 +1,447 @@
1
+ function resolveBorderSides(width) {
2
+ if (width === void 0) return { top: 0, right: 0, bottom: 0, left: 0 };
3
+ if (typeof width === "number") {
4
+ const w = Math.max(0, width);
5
+ return { top: w, right: w, bottom: w, left: w };
6
+ }
7
+ return {
8
+ top: Math.max(0, width.top ?? 0),
9
+ right: Math.max(0, width.right ?? 0),
10
+ bottom: Math.max(0, width.bottom ?? 0),
11
+ left: Math.max(0, width.left ?? 0)
12
+ };
13
+ }
14
+ function isUniformBorder(sides) {
15
+ return sides.top === sides.right && sides.right === sides.bottom && sides.bottom === sides.left;
16
+ }
17
+ function resolveCornerRadii(cr) {
18
+ if (typeof cr === "number") {
19
+ const r = Math.max(0, cr);
20
+ return { tl: r, tr: r, bl: r, br: r };
21
+ }
22
+ if (cr) {
23
+ return {
24
+ tl: Math.max(0, cr.tl ?? 0),
25
+ tr: Math.max(0, cr.tr ?? 0),
26
+ bl: Math.max(0, cr.bl ?? 0),
27
+ br: Math.max(0, cr.br ?? 0)
28
+ };
29
+ }
30
+ return { tl: 0, tr: 0, bl: 0, br: 0 };
31
+ }
32
+ function hasAnyCornerRadius(corners) {
33
+ return corners.tl > 0 || corners.tr > 0 || corners.bl > 0 || corners.br > 0;
34
+ }
35
+ function shouldUseCoreBorderGeometry(border, rendererIssues) {
36
+ const sides = resolveBorderSides(border.width);
37
+ const asymmetric = !isUniformBorder(sides);
38
+ if (asymmetric) return true;
39
+ if (rendererIssues && rendererIssues.length > 0) {
40
+ if (rendererIssues.includes("all")) return true;
41
+ if (rendererIssues.includes("rounded-dotted") && border.style === "dotted") {
42
+ return true;
43
+ }
44
+ if (rendererIssues.includes("rounded-dashed-cap") && border.style === "dashed") {
45
+ return true;
46
+ }
47
+ }
48
+ return false;
49
+ }
50
+ function pushPerimeterPoint(points, pt, width) {
51
+ const last = points[points.length - 1];
52
+ if (!last || Math.abs(last.x - pt.x) > 1e-3 || Math.abs(last.y - pt.y) > 1e-3) {
53
+ points.push({ x: pt.x, y: pt.y, width });
54
+ return;
55
+ }
56
+ last.width = width;
57
+ }
58
+ function appendPerimeterArcPoints(points, corner, startAngle, endAngle, widthStart, widthEnd) {
59
+ const start = pointOnEllipse(corner, startAngle);
60
+ pushPerimeterPoint(points, start, widthStart);
61
+ if (corner.rx <= 0 || corner.ry <= 0) {
62
+ pushPerimeterPoint(points, pointOnEllipse(corner, endAngle), widthEnd);
63
+ return;
64
+ }
65
+ const span = endAngle - startAngle;
66
+ const maxR = Math.max(corner.rx, corner.ry);
67
+ const steps = Math.max(1, Math.min(24, Math.ceil(Math.abs(span) * maxR / 8)));
68
+ for (let i = 1; i <= steps; i++) {
69
+ const t = i / steps;
70
+ const angle = startAngle + span * t;
71
+ const width = widthStart + (widthEnd - widthStart) * t;
72
+ pushPerimeterPoint(points, pointOnEllipse(corner, angle), width);
73
+ }
74
+ }
75
+ function buildPerimeterPoints(w, h, sides, corners, align) {
76
+ const offsets = resolveBorderOffsets(sides, align);
77
+ const outer = buildOuterContour(w, h, corners, offsets.outer);
78
+ const inner = buildInnerContour(w, h, corners, offsets.inner);
79
+ const mid = averageContours(outer, inner);
80
+ const points = [];
81
+ pushPerimeterPoint(points, { x: mid.tl.cx, y: mid.top }, sides.top);
82
+ pushPerimeterPoint(points, { x: mid.tr.cx, y: mid.top }, sides.top);
83
+ appendPerimeterArcPoints(points, mid.tr, -Math.PI / 2, 0, sides.top, sides.right);
84
+ pushPerimeterPoint(points, { x: mid.right, y: mid.br.cy }, sides.right);
85
+ appendPerimeterArcPoints(points, mid.br, 0, Math.PI / 2, sides.right, sides.bottom);
86
+ pushPerimeterPoint(points, { x: mid.bl.cx, y: mid.bottom }, sides.bottom);
87
+ appendPerimeterArcPoints(points, mid.bl, Math.PI / 2, Math.PI, sides.bottom, sides.left);
88
+ pushPerimeterPoint(points, { x: mid.left, y: mid.tl.cy }, sides.left);
89
+ appendPerimeterArcPoints(points, mid.tl, Math.PI, Math.PI * 1.5, sides.left, sides.top);
90
+ if (points.length > 1) {
91
+ const first = points[0] ?? { x: 0, y: 0 };
92
+ const last = points[points.length - 1] ?? { x: 0, y: 0 };
93
+ if (Math.abs(first.x - last.x) <= 1e-3 && Math.abs(first.y - last.y) <= 1e-3) {
94
+ points.pop();
95
+ }
96
+ }
97
+ return points;
98
+ }
99
+ function buildPerimeterSegments(points) {
100
+ if (points.length < 2) return [];
101
+ const segs = [];
102
+ for (let i = 0; i < points.length; i++) {
103
+ const p1 = points[i] ?? { x: 0, y: 0, width: 0 };
104
+ const p2 = points[(i + 1) % points.length] ?? { x: 0, y: 0, width: 0 };
105
+ const dx = p2.x - p1.x;
106
+ const dy = p2.y - p1.y;
107
+ const length = Math.sqrt(dx * dx + dy * dy);
108
+ if (length <= 1e-3) continue;
109
+ segs.push({
110
+ x1: p1.x,
111
+ y1: p1.y,
112
+ x2: p2.x,
113
+ y2: p2.y,
114
+ width1: p1.width,
115
+ width2: p2.width,
116
+ length
117
+ });
118
+ }
119
+ return segs;
120
+ }
121
+ function pointAtDistance(seg, t) {
122
+ const frac = seg.length > 0 ? t / seg.length : 0;
123
+ return {
124
+ x: seg.x1 + (seg.x2 - seg.x1) * frac,
125
+ y: seg.y1 + (seg.y2 - seg.y1) * frac,
126
+ width: seg.width1 + (seg.width2 - seg.width1) * frac
127
+ };
128
+ }
129
+ function resolveBorderOffsets(sides, align) {
130
+ if (align === "inside") {
131
+ return {
132
+ outer: { top: 0, right: 0, bottom: 0, left: 0 },
133
+ inner: { ...sides }
134
+ };
135
+ }
136
+ if (align === "outside") {
137
+ return {
138
+ outer: { ...sides },
139
+ inner: { top: 0, right: 0, bottom: 0, left: 0 }
140
+ };
141
+ }
142
+ return {
143
+ outer: {
144
+ top: sides.top / 2,
145
+ right: sides.right / 2,
146
+ bottom: sides.bottom / 2,
147
+ left: sides.left / 2
148
+ },
149
+ inner: {
150
+ top: sides.top / 2,
151
+ right: sides.right / 2,
152
+ bottom: sides.bottom / 2,
153
+ left: sides.left / 2
154
+ }
155
+ };
156
+ }
157
+ function buildOuterContour(w, h, corners, offsets) {
158
+ const left = -offsets.left;
159
+ const top = -offsets.top;
160
+ const right = w + offsets.right;
161
+ const bottom = h + offsets.bottom;
162
+ return {
163
+ left,
164
+ top,
165
+ right,
166
+ bottom,
167
+ tl: {
168
+ cx: corners.tl,
169
+ cy: corners.tl,
170
+ rx: corners.tl + offsets.left,
171
+ ry: corners.tl + offsets.top
172
+ },
173
+ tr: {
174
+ cx: w - corners.tr,
175
+ cy: corners.tr,
176
+ rx: corners.tr + offsets.right,
177
+ ry: corners.tr + offsets.top
178
+ },
179
+ br: {
180
+ cx: w - corners.br,
181
+ cy: h - corners.br,
182
+ rx: corners.br + offsets.right,
183
+ ry: corners.br + offsets.bottom
184
+ },
185
+ bl: {
186
+ cx: corners.bl,
187
+ cy: h - corners.bl,
188
+ rx: corners.bl + offsets.left,
189
+ ry: corners.bl + offsets.bottom
190
+ }
191
+ };
192
+ }
193
+ function buildInnerContour(w, h, corners, offsets) {
194
+ const left = offsets.left;
195
+ const top = offsets.top;
196
+ const right = w - offsets.right;
197
+ const bottom = h - offsets.bottom;
198
+ const tlRx = Math.max(0, corners.tl - offsets.left);
199
+ const tlRy = Math.max(0, corners.tl - offsets.top);
200
+ const trRx = Math.max(0, corners.tr - offsets.right);
201
+ const trRy = Math.max(0, corners.tr - offsets.top);
202
+ const brRx = Math.max(0, corners.br - offsets.right);
203
+ const brRy = Math.max(0, corners.br - offsets.bottom);
204
+ const blRx = Math.max(0, corners.bl - offsets.left);
205
+ const blRy = Math.max(0, corners.bl - offsets.bottom);
206
+ return {
207
+ left,
208
+ top,
209
+ right,
210
+ bottom,
211
+ tl: { cx: left + tlRx, cy: top + tlRy, rx: tlRx, ry: tlRy },
212
+ tr: { cx: right - trRx, cy: top + trRy, rx: trRx, ry: trRy },
213
+ br: { cx: right - brRx, cy: bottom - brRy, rx: brRx, ry: brRy },
214
+ bl: { cx: left + blRx, cy: bottom - blRy, rx: blRx, ry: blRy }
215
+ };
216
+ }
217
+ function averageContours(a, b) {
218
+ const avgCorner = (ca, cb, sideX, sideY, right = false, bottom = false) => {
219
+ const rx = (ca.rx + cb.rx) / 2;
220
+ const ry = (ca.ry + cb.ry) / 2;
221
+ return {
222
+ cx: right ? sideX - rx : sideX + rx,
223
+ cy: bottom ? sideY - ry : sideY + ry,
224
+ rx,
225
+ ry
226
+ };
227
+ };
228
+ return {
229
+ left: (a.left + b.left) / 2,
230
+ top: (a.top + b.top) / 2,
231
+ right: (a.right + b.right) / 2,
232
+ bottom: (a.bottom + b.bottom) / 2,
233
+ tl: avgCorner(a.tl, b.tl, (a.left + b.left) / 2, (a.top + b.top) / 2),
234
+ tr: avgCorner(a.tr, b.tr, (a.right + b.right) / 2, (a.top + b.top) / 2, true, false),
235
+ br: avgCorner(a.br, b.br, (a.right + b.right) / 2, (a.bottom + b.bottom) / 2, true, true),
236
+ bl: avgCorner(a.bl, b.bl, (a.left + b.left) / 2, (a.bottom + b.bottom) / 2, false, true)
237
+ };
238
+ }
239
+ function pointOnEllipse(corner, angle) {
240
+ return {
241
+ x: corner.cx + corner.rx * Math.cos(angle),
242
+ y: corner.cy + corner.ry * Math.sin(angle)
243
+ };
244
+ }
245
+ function pushPoint(points, pt) {
246
+ const last = points[points.length - 1];
247
+ if (!last || Math.abs(last.x - pt.x) > 1e-3 || Math.abs(last.y - pt.y) > 1e-3) {
248
+ points.push(pt);
249
+ }
250
+ }
251
+ function appendEllipseArcPoints(points, corner, startAngle, endAngle) {
252
+ const start = pointOnEllipse(corner, startAngle);
253
+ const end = pointOnEllipse(corner, endAngle);
254
+ pushPoint(points, start);
255
+ if (corner.rx <= 0 || corner.ry <= 0) {
256
+ pushPoint(points, end);
257
+ return;
258
+ }
259
+ const span = endAngle - startAngle;
260
+ const maxR = Math.max(corner.rx, corner.ry);
261
+ const steps = Math.max(1, Math.min(24, Math.ceil(Math.abs(span) * maxR / 8)));
262
+ for (let i = 1; i <= steps; i++) {
263
+ const t = i / steps;
264
+ const angle = startAngle + span * t;
265
+ pushPoint(points, pointOnEllipse(corner, angle));
266
+ }
267
+ }
268
+ function buildContourPoints(contour) {
269
+ const points = [];
270
+ pushPoint(points, { x: contour.tl.cx, y: contour.top });
271
+ pushPoint(points, { x: contour.tr.cx, y: contour.top });
272
+ appendEllipseArcPoints(points, contour.tr, -Math.PI / 2, 0);
273
+ pushPoint(points, { x: contour.right, y: contour.br.cy });
274
+ appendEllipseArcPoints(points, contour.br, 0, Math.PI / 2);
275
+ pushPoint(points, { x: contour.bl.cx, y: contour.bottom });
276
+ appendEllipseArcPoints(points, contour.bl, Math.PI / 2, Math.PI);
277
+ pushPoint(points, { x: contour.left, y: contour.tl.cy });
278
+ appendEllipseArcPoints(points, contour.tl, Math.PI, Math.PI * 1.5);
279
+ return points;
280
+ }
281
+ function traceClosedPath(ctx, points) {
282
+ if (points.length === 0) return;
283
+ if (points[0] === void 0) return;
284
+ ctx.moveTo(points[0].x, points[0].y);
285
+ for (let i = 1; i < points.length; i++) {
286
+ const pt = points[i] ?? { x: 0, y: 0 };
287
+ ctx.lineTo(pt.x, pt.y);
288
+ }
289
+ ctx.closePath();
290
+ }
291
+ function drawSolidBorder(ctx, w, h, sides, corners, color, alpha, align) {
292
+ const offsets = resolveBorderOffsets(sides, align);
293
+ const outer = buildOuterContour(w, h, corners, offsets.outer);
294
+ const inner = buildInnerContour(w, h, corners, offsets.inner);
295
+ const outerPoints = buildContourPoints(outer);
296
+ const innerPoints = buildContourPoints(inner);
297
+ if (outerPoints.length < 3) return;
298
+ ctx.fillStyle(color, alpha);
299
+ ctx.beginPath();
300
+ traceClosedPath(ctx, outerPoints);
301
+ traceClosedPath(ctx, [...innerPoints].reverse());
302
+ ctx.fillPath();
303
+ }
304
+ function appendDashPoint(points, pt) {
305
+ const last = points[points.length - 1];
306
+ if (!last || Math.abs(last.x - pt.x) > 1e-3 || Math.abs(last.y - pt.y) > 1e-3) {
307
+ points.push(pt);
308
+ }
309
+ }
310
+ function strokeDashedPath(ctx, points, widths, color, alpha) {
311
+ if (points.length < 2 || widths.length === 0) return;
312
+ const width = widths.reduce((sum, value) => sum + value, 0) / widths.length;
313
+ if (width <= 0) return;
314
+ ctx.lineStyle(width, color, alpha);
315
+ ctx.beginPath();
316
+ if (points[0] === void 0) return;
317
+ ctx.moveTo(points[0].x, points[0].y);
318
+ for (let i = 1; i < points.length; i++) {
319
+ const pt = points[i];
320
+ if (pt === void 0) continue;
321
+ ctx.lineTo(pt.x, pt.y);
322
+ }
323
+ ctx.strokePath();
324
+ }
325
+ function drawDashedBorder(ctx, w, h, sides, corners, border, color, alpha, align) {
326
+ const segs = buildPerimeterSegments(buildPerimeterPoints(w, h, sides, corners, align));
327
+ if (segs.length === 0) return;
328
+ const maxWidth = Math.max(sides.top, sides.right, sides.bottom, sides.left);
329
+ const dashArray = border.dash ?? [maxWidth * 3, maxWidth * 2];
330
+ const dashOffset = border.dashOffset ?? 0;
331
+ const pattern = dashArray.length % 2 === 0 ? dashArray : [...dashArray, ...dashArray];
332
+ const patternSum = pattern.reduce((a, b) => a + b, 0);
333
+ if (patternSum <= 0) return;
334
+ let patIdx = 0;
335
+ let drawing = true;
336
+ let accumulated = pattern[0] ?? 0;
337
+ let offset = dashOffset % patternSum;
338
+ if (offset < 0) offset += patternSum;
339
+ while (offset > 1e-3) {
340
+ const consume = Math.min(offset, accumulated);
341
+ offset -= consume;
342
+ accumulated -= consume;
343
+ if (accumulated <= 1e-3) {
344
+ patIdx = (patIdx + 1) % pattern.length;
345
+ drawing = !drawing;
346
+ accumulated = pattern[patIdx] ?? 0;
347
+ }
348
+ }
349
+ let dashPoints = [];
350
+ let dashWidths = [];
351
+ const flushDash = () => {
352
+ if (dashPoints.length > 1) {
353
+ strokeDashedPath(ctx, dashPoints, dashWidths, color, alpha);
354
+ }
355
+ dashPoints = [];
356
+ dashWidths = [];
357
+ };
358
+ for (const seg of segs) {
359
+ const sLen = seg.length;
360
+ if (sLen <= 0) continue;
361
+ let t = 0;
362
+ while (t < sLen) {
363
+ const consume = Math.min(accumulated, sLen - t);
364
+ const end = t + consume;
365
+ if (drawing && consume > 0) {
366
+ const p1 = pointAtDistance(seg, t);
367
+ const p2 = pointAtDistance(seg, end);
368
+ if (dashPoints.length === 0) {
369
+ appendDashPoint(dashPoints, p1);
370
+ dashWidths.push(p1.width);
371
+ }
372
+ appendDashPoint(dashPoints, p2);
373
+ dashWidths.push((p1.width + p2.width) / 2);
374
+ }
375
+ t += consume;
376
+ accumulated -= consume;
377
+ if (accumulated <= 1e-3) {
378
+ if (drawing) flushDash();
379
+ patIdx = (patIdx + 1) % pattern.length;
380
+ drawing = !drawing;
381
+ accumulated = pattern[patIdx] ?? 0;
382
+ }
383
+ }
384
+ }
385
+ if (drawing) flushDash();
386
+ }
387
+ function drawDottedBorder(ctx, w, h, sides, corners, border, color, alpha, align) {
388
+ const segs = buildPerimeterSegments(buildPerimeterPoints(w, h, sides, corners, align));
389
+ if (segs.length === 0) return;
390
+ const dotGap = border.dash?.[0] ?? Math.max(sides.top, sides.right, sides.bottom, sides.left);
391
+ const dotDiameterOverride = border.dash?.[1];
392
+ const totalLength = segs.reduce((sum, seg) => sum + seg.length, 0);
393
+ if (totalLength <= 0) return;
394
+ const fallbackDiameter = Math.max(sides.top, sides.right, sides.bottom, sides.left);
395
+ const baseDiameter = dotDiameterOverride ?? fallbackDiameter;
396
+ const step = baseDiameter + dotGap;
397
+ if (step <= 0) return;
398
+ let distance = step / 2 + (border.dashOffset ?? 0);
399
+ while (distance < 0) distance += step;
400
+ for (; distance < totalLength; distance += step) {
401
+ let remaining = distance;
402
+ for (const seg of segs) {
403
+ if (remaining <= seg.length) {
404
+ const pt = pointAtDistance(seg, remaining);
405
+ const dotDiameter = dotDiameterOverride ?? pt.width;
406
+ const dotRadius = dotDiameter / 2;
407
+ if (dotRadius > 0) {
408
+ ctx.fillCircleStyled(pt.x, pt.y, dotRadius, color, alpha);
409
+ }
410
+ break;
411
+ }
412
+ remaining -= seg.length;
413
+ }
414
+ }
415
+ }
416
+ function drawBorderGeometry(ctx, input, border) {
417
+ const { box, sides, corners } = input;
418
+ const { w, h } = box;
419
+ const color = border.color ?? 16777215;
420
+ const alpha = typeof border.alpha === "number" ? border.alpha : 1;
421
+ const maxSw = Math.max(sides.top, sides.right, sides.bottom, sides.left);
422
+ if (maxSw <= 0) return;
423
+ if (w <= 0 || h <= 0) return;
424
+ const align = border.align ?? "center";
425
+ const style = border.style ?? "solid";
426
+ switch (style) {
427
+ case "dotted":
428
+ drawDottedBorder(ctx, w, h, sides, corners, border, color, alpha, align);
429
+ break;
430
+ case "dashed":
431
+ drawDashedBorder(ctx, w, h, sides, corners, border, color, alpha, align);
432
+ break;
433
+ case "solid":
434
+ default:
435
+ drawSolidBorder(ctx, w, h, sides, corners, color, alpha, align);
436
+ break;
437
+ }
438
+ }
439
+ export {
440
+ drawBorderGeometry,
441
+ hasAnyCornerRadius,
442
+ isUniformBorder,
443
+ resolveBorderSides,
444
+ resolveCornerRadii,
445
+ shouldUseCoreBorderGeometry
446
+ };
447
+ //# sourceMappingURL=border-geometry.js.map