@ojiepermana/angular 22.1.11 → 22.1.12

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/README.md +32 -26
  2. package/chart/README.md +272 -0
  3. package/component/README.md +89 -0
  4. package/component/accordion/README.md +195 -0
  5. package/component/alert/README.md +184 -0
  6. package/component/alert-dialog/README.md +255 -0
  7. package/component/aspect-ratio/README.md +116 -0
  8. package/component/avatar/README.md +182 -0
  9. package/component/badge/README.md +143 -0
  10. package/component/breadcrumb/README.md +223 -0
  11. package/component/button/README.md +141 -0
  12. package/component/button-group/README.md +214 -0
  13. package/component/calendar/README.md +137 -0
  14. package/component/card/README.md +232 -0
  15. package/component/carousel/README.md +276 -0
  16. package/component/checkbox/README.md +153 -0
  17. package/component/collapsible/README.md +216 -0
  18. package/component/combobox/README.md +202 -0
  19. package/component/command/README.md +287 -0
  20. package/component/composer/README.md +241 -0
  21. package/component/context-menu/README.md +268 -0
  22. package/component/date-picker/README.md +202 -0
  23. package/component/dialog/README.md +276 -0
  24. package/component/drawer/README.md +147 -0
  25. package/component/dropdown-menu/README.md +336 -0
  26. package/component/editor/README.md +152 -0
  27. package/component/empty/README.md +193 -0
  28. package/component/form/README.md +216 -0
  29. package/component/hover-card/README.md +150 -0
  30. package/component/icon/README.md +25 -0
  31. package/component/input/README.md +160 -0
  32. package/component/input-group/README.md +245 -0
  33. package/component/input-otp/README.md +331 -0
  34. package/component/item/README.md +254 -0
  35. package/component/kanban/README.md +81 -0
  36. package/component/kbd/README.md +141 -0
  37. package/component/label/README.md +137 -0
  38. package/component/menubar/README.md +270 -0
  39. package/component/native-select/README.md +176 -0
  40. package/component/navigation-menu/README.md +165 -0
  41. package/component/pagination/README.md +151 -0
  42. package/component/pillbox/README.md +68 -0
  43. package/component/popover/README.md +54 -0
  44. package/component/progress/README.md +160 -0
  45. package/component/radio/README.md +212 -0
  46. package/component/resizable/README.md +178 -0
  47. package/component/scroll-area/README.md +150 -0
  48. package/component/select/README.md +228 -0
  49. package/component/separator/README.md +175 -0
  50. package/component/sheet/README.md +190 -0
  51. package/component/skeleton/README.md +158 -0
  52. package/component/slider/README.md +207 -0
  53. package/component/spinner/README.md +160 -0
  54. package/component/switch/README.md +170 -0
  55. package/component/table/README.md +292 -0
  56. package/component/tabs/README.md +220 -0
  57. package/component/textarea/README.md +169 -0
  58. package/component/timeline/README.md +94 -0
  59. package/component/toast/README.md +173 -0
  60. package/component/toggle/README.md +133 -0
  61. package/component/toggle-group/README.md +234 -0
  62. package/component/tooltip/README.md +230 -0
  63. package/fesm2022/ojiepermana-angular-chart-area.mjs +289 -3
  64. package/fesm2022/ojiepermana-angular-chart-bar.mjs +722 -3
  65. package/fesm2022/ojiepermana-angular-chart-core.mjs +1482 -3
  66. package/fesm2022/ojiepermana-angular-chart-line.mjs +294 -3
  67. package/fesm2022/ojiepermana-angular-chart-pie.mjs +291 -3
  68. package/fesm2022/ojiepermana-angular-chart-primitives.mjs +1301 -3
  69. package/fesm2022/ojiepermana-angular-chart-radar.mjs +421 -3
  70. package/fesm2022/ojiepermana-angular-chart-radial.mjs +295 -3
  71. package/fesm2022/ojiepermana-angular-chart-scatter.mjs +306 -3
  72. package/fesm2022/ojiepermana-angular-chart.mjs +12 -3
  73. package/fesm2022/ojiepermana-angular-component-accordion.mjs +267 -3
  74. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +359 -3
  75. package/fesm2022/ojiepermana-angular-component-alert.mjs +101 -3
  76. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +31 -3
  77. package/fesm2022/ojiepermana-angular-component-avatar.mjs +139 -3
  78. package/fesm2022/ojiepermana-angular-component-badge.mjs +57 -3
  79. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +192 -3
  80. package/fesm2022/ojiepermana-angular-component-button-group.mjs +95 -3
  81. package/fesm2022/ojiepermana-angular-component-button.mjs +73 -3
  82. package/fesm2022/ojiepermana-angular-component-calendar.mjs +718 -3
  83. package/fesm2022/ojiepermana-angular-component-card.mjs +167 -3
  84. package/fesm2022/ojiepermana-angular-component-carousel.mjs +326 -3
  85. package/fesm2022/ojiepermana-angular-component-checkbox.mjs +190 -3
  86. package/fesm2022/ojiepermana-angular-component-collapsible.mjs +117 -3
  87. package/fesm2022/ojiepermana-angular-component-combobox.mjs +327 -3
  88. package/fesm2022/ojiepermana-angular-component-command.mjs +351 -3
  89. package/fesm2022/ojiepermana-angular-component-composer.mjs +359 -3
  90. package/fesm2022/ojiepermana-angular-component-context-menu.mjs +158 -3
  91. package/fesm2022/ojiepermana-angular-component-date-picker.mjs +482 -3
  92. package/fesm2022/ojiepermana-angular-component-dialog.mjs +400 -3
  93. package/fesm2022/ojiepermana-angular-component-drawer.mjs +1 -3
  94. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +689 -3
  95. package/fesm2022/ojiepermana-angular-component-editor.mjs +511 -3
  96. package/fesm2022/ojiepermana-angular-component-empty.mjs +134 -3
  97. package/fesm2022/ojiepermana-angular-component-form.mjs +438 -3
  98. package/fesm2022/ojiepermana-angular-component-hover-card.mjs +273 -3
  99. package/fesm2022/ojiepermana-angular-component-icon.mjs +139 -3
  100. package/fesm2022/ojiepermana-angular-component-input-group.mjs +176 -3
  101. package/fesm2022/ojiepermana-angular-component-input-otp.mjs +550 -3
  102. package/fesm2022/ojiepermana-angular-component-input.mjs +52 -3
  103. package/fesm2022/ojiepermana-angular-component-item.mjs +264 -3
  104. package/fesm2022/ojiepermana-angular-component-kanban.mjs +310 -3
  105. package/fesm2022/ojiepermana-angular-component-kbd.mjs +48 -3
  106. package/fesm2022/ojiepermana-angular-component-label.mjs +27 -3
  107. package/fesm2022/ojiepermana-angular-component-menubar.mjs +327 -3
  108. package/fesm2022/ojiepermana-angular-component-native-select.mjs +62 -3
  109. package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +378 -3
  110. package/fesm2022/ojiepermana-angular-component-pagination.mjs +238 -3
  111. package/fesm2022/ojiepermana-angular-component-pillbox.mjs +999 -3
  112. package/fesm2022/ojiepermana-angular-component-popover.mjs +201 -3
  113. package/fesm2022/ojiepermana-angular-component-progress.mjs +57 -3
  114. package/fesm2022/ojiepermana-angular-component-radio.mjs +180 -3
  115. package/fesm2022/ojiepermana-angular-component-resizable.mjs +493 -3
  116. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +51 -3
  117. package/fesm2022/ojiepermana-angular-component-segmented-control.mjs +227 -3
  118. package/fesm2022/ojiepermana-angular-component-select.mjs +609 -3
  119. package/fesm2022/ojiepermana-angular-component-separator.mjs +31 -3
  120. package/fesm2022/ojiepermana-angular-component-sheet.mjs +407 -3
  121. package/fesm2022/ojiepermana-angular-component-skeleton.mjs +25 -3
  122. package/fesm2022/ojiepermana-angular-component-slider.mjs +456 -3
  123. package/fesm2022/ojiepermana-angular-component-spinner.mjs +56 -3
  124. package/fesm2022/ojiepermana-angular-component-switch.mjs +145 -3
  125. package/fesm2022/ojiepermana-angular-component-table.mjs +155 -3
  126. package/fesm2022/ojiepermana-angular-component-tabs.mjs +315 -3
  127. package/fesm2022/ojiepermana-angular-component-textarea.mjs +46 -3
  128. package/fesm2022/ojiepermana-angular-component-timeline.mjs +237 -3
  129. package/fesm2022/ojiepermana-angular-component-toast.mjs +241 -3
  130. package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +290 -3
  131. package/fesm2022/ojiepermana-angular-component-toggle.mjs +76 -3
  132. package/fesm2022/ojiepermana-angular-component-tooltip.mjs +519 -3
  133. package/fesm2022/ojiepermana-angular-component-utils-core.mjs +310 -3
  134. package/fesm2022/ojiepermana-angular-component-utils-overlay.mjs +62 -3
  135. package/fesm2022/ojiepermana-angular-component-utils-scale.mjs +34 -3
  136. package/fesm2022/ojiepermana-angular-component-utils.mjs +3 -2
  137. package/fesm2022/ojiepermana-angular-component.mjs +4 -4
  138. package/fesm2022/ojiepermana-angular-navigation-core.mjs +21 -3
  139. package/fesm2022/ojiepermana-angular-navigation-icon.mjs +20 -3
  140. package/fesm2022/ojiepermana-angular-navigation-navigation-badge-count.component-CDBxQ8rk.mjs +91 -0
  141. package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-DBQHdvGa.mjs +512 -0
  142. package/fesm2022/ojiepermana-angular-navigation-navigation-entry-grid.component-Cd-jh6tg.mjs +623 -0
  143. package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-BCGvhoYj.mjs +404 -0
  144. package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-Dk_03e-6.mjs +466 -0
  145. package/fesm2022/ojiepermana-angular-navigation-ojiepermana-angular-navigation-DNKU6viC.mjs +2642 -0
  146. package/fesm2022/ojiepermana-angular-navigation-service.mjs +725 -3
  147. package/fesm2022/ojiepermana-angular-navigation-types.mjs +65 -4
  148. package/fesm2022/ojiepermana-angular-navigation.mjs +4 -10
  149. package/fesm2022/ojiepermana-angular-sdk.mjs +204 -4
  150. package/fesm2022/ojiepermana-angular-theme-component-settings.mjs +1387 -3
  151. package/fesm2022/ojiepermana-angular-theme-layout-services.mjs +331 -3
  152. package/fesm2022/ojiepermana-angular-theme-layout-types.mjs +45 -4
  153. package/fesm2022/ojiepermana-angular-theme-layout-wrapper.mjs +1044 -3
  154. package/fesm2022/ojiepermana-angular-theme-layout.mjs +729 -3
  155. package/fesm2022/ojiepermana-angular-theme-page-core.mjs +381 -3
  156. package/fesm2022/ojiepermana-angular-theme-page-filter.mjs +267 -3
  157. package/fesm2022/ojiepermana-angular-theme-page-root.mjs +361 -3
  158. package/fesm2022/ojiepermana-angular-theme-page-side.mjs +198 -3
  159. package/fesm2022/ojiepermana-angular-theme-page-slots.mjs +110 -3
  160. package/fesm2022/ojiepermana-angular-theme-page.mjs +7 -2
  161. package/fesm2022/ojiepermana-angular-theme-shell-services.mjs +338 -3
  162. package/fesm2022/ojiepermana-angular-theme-shell-types.mjs +160 -4
  163. package/fesm2022/ojiepermana-angular-theme-shell.mjs +811 -3
  164. package/fesm2022/ojiepermana-angular-theme-styles.mjs +783 -3
  165. package/fesm2022/ojiepermana-angular-theme.mjs +4 -4
  166. package/fesm2022/ojiepermana-angular.mjs +6 -11
  167. package/navigation/README.md +374 -0
  168. package/package.json +81 -20
  169. package/sdk/README.md +212 -0
  170. package/sdk/schematics/collection.json +20 -0
  171. package/sdk/schematics/init/index.js +83 -0
  172. package/sdk/schematics/init/schema.json +19 -0
  173. package/sdk/schematics/ng-add/index.js +147 -0
  174. package/sdk/schematics/ng-add/schema.json +14 -0
  175. package/sdk/schematics/package.json +3 -0
  176. package/sdk/schematics/sdk/index.js +175 -0
  177. package/sdk/schematics/sdk/schema.json +19 -0
  178. package/sdk/sdk.config.example.json +24 -0
  179. package/sdk/src/config/loader.js +43 -0
  180. package/sdk/src/config/schema.js +59 -0
  181. package/sdk/src/emit/client.js +251 -0
  182. package/sdk/src/emit/metadata.js +310 -0
  183. package/sdk/src/emit/models.js +104 -0
  184. package/sdk/src/emit/navigation.js +56 -0
  185. package/sdk/src/emit/operations.js +118 -0
  186. package/sdk/src/emit/public-api.js +54 -0
  187. package/sdk/src/emit/services.js +110 -0
  188. package/sdk/src/engine.js +67 -0
  189. package/sdk/src/layout/per-domain.js +360 -0
  190. package/sdk/src/package.json +3 -0
  191. package/sdk/src/parser/bundle.js +25 -0
  192. package/sdk/src/parser/ir.js +429 -0
  193. package/sdk/src/parser/types.js +7 -0
  194. package/sdk/src/render/template.js +152 -0
  195. package/sdk/src/writer/index.js +286 -0
  196. package/theme/README.md +126 -0
  197. package/theme/component/settings/README.md +135 -0
  198. package/theme/layout/README.md +539 -0
  199. package/theme/page/README.md +453 -0
  200. package/theme/shell/README.md +340 -0
  201. package/theme/styles/README.md +178 -0
  202. package/theme/styles/css/base/components.css +553 -0
  203. package/theme/styles/css/base/index.css +14 -0
  204. package/theme/styles/css/base/package.css +9 -0
  205. package/theme/styles/css/base/prefers-dark.css +86 -0
  206. package/theme/styles/css/base/print.css +62 -0
  207. package/theme/styles/css/base/status.css +38 -0
  208. package/theme/styles/css/base/tailwind.css +165 -0
  209. package/theme/styles/css/base/theme.css +373 -0
  210. package/theme/styles/css/base/tokens.css +361 -0
  211. package/theme/styles/css/color/amber.css +72 -0
  212. package/theme/styles/css/color/blue.css +72 -0
  213. package/theme/styles/css/color/brand.css +38 -0
  214. package/theme/styles/css/color/cyan.css +72 -0
  215. package/theme/styles/css/color/emerald.css +72 -0
  216. package/theme/styles/css/color/fuchsia.css +72 -0
  217. package/theme/styles/css/color/green.css +72 -0
  218. package/theme/styles/css/color/index.css +19 -0
  219. package/theme/styles/css/color/indigo.css +72 -0
  220. package/theme/styles/css/color/lime.css +72 -0
  221. package/theme/styles/css/color/orange.css +72 -0
  222. package/theme/styles/css/color/pink.css +72 -0
  223. package/theme/styles/css/color/purple.css +72 -0
  224. package/theme/styles/css/color/red.css +72 -0
  225. package/theme/styles/css/color/rose.css +72 -0
  226. package/theme/styles/css/color/sky.css +72 -0
  227. package/theme/styles/css/color/teal.css +72 -0
  228. package/theme/styles/css/color/violet.css +72 -0
  229. package/theme/styles/css/color/yellow.css +72 -0
  230. package/theme/styles/css/index.css +18 -0
  231. package/theme/styles/css/neutral/gray.css +63 -0
  232. package/theme/styles/css/neutral/index.css +11 -0
  233. package/theme/styles/css/neutral/mauve.css +63 -0
  234. package/theme/styles/css/neutral/mist.css +63 -0
  235. package/theme/styles/css/neutral/neutral.css +63 -0
  236. package/theme/styles/css/neutral/olive.css +63 -0
  237. package/theme/styles/css/neutral/slate.css +63 -0
  238. package/theme/styles/css/neutral/stone.css +63 -0
  239. package/theme/styles/css/neutral/taupe.css +63 -0
  240. package/theme/styles/css/neutral/zinc.css +63 -0
  241. package/theme/styles/css/radius/index.css +30 -0
  242. package/theme/styles/css/space/index.css +20 -0
  243. package/types/ojiepermana-angular-chart-area.d.ts +76 -1
  244. package/types/ojiepermana-angular-chart-bar.d.ts +201 -1
  245. package/types/ojiepermana-angular-chart-core.d.ts +811 -1
  246. package/types/ojiepermana-angular-chart-line.d.ts +75 -1
  247. package/types/ojiepermana-angular-chart-pie.d.ts +131 -1
  248. package/types/ojiepermana-angular-chart-primitives.d.ts +291 -1
  249. package/types/ojiepermana-angular-chart-radar.d.ts +116 -1
  250. package/types/ojiepermana-angular-chart-radial.d.ts +116 -1
  251. package/types/ojiepermana-angular-chart-scatter.d.ts +125 -1
  252. package/types/ojiepermana-angular-chart.d.ts +2 -1
  253. package/types/ojiepermana-angular-component-accordion.d.ts +85 -1
  254. package/types/ojiepermana-angular-component-alert-dialog.d.ts +140 -1
  255. package/types/ojiepermana-angular-component-alert.d.ts +42 -1
  256. package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -1
  257. package/types/ojiepermana-angular-component-avatar.d.ts +56 -1
  258. package/types/ojiepermana-angular-component-badge.d.ts +24 -1
  259. package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -1
  260. package/types/ojiepermana-angular-component-button-group.d.ts +26 -1
  261. package/types/ojiepermana-angular-component-button.d.ts +27 -1
  262. package/types/ojiepermana-angular-component-calendar.d.ts +111 -1
  263. package/types/ojiepermana-angular-component-card.d.ts +69 -1
  264. package/types/ojiepermana-angular-component-carousel.d.ts +86 -1
  265. package/types/ojiepermana-angular-component-checkbox.d.ts +42 -1
  266. package/types/ojiepermana-angular-component-collapsible.d.ts +42 -1
  267. package/types/ojiepermana-angular-component-combobox.d.ts +60 -1
  268. package/types/ojiepermana-angular-component-command.d.ts +130 -1
  269. package/types/ojiepermana-angular-component-composer.d.ts +90 -1
  270. package/types/ojiepermana-angular-component-context-menu.d.ts +54 -1
  271. package/types/ojiepermana-angular-component-date-picker.d.ts +109 -1
  272. package/types/ojiepermana-angular-component-dialog.d.ts +136 -1
  273. package/types/ojiepermana-angular-component-drawer.d.ts +1 -1
  274. package/types/ojiepermana-angular-component-dropdown-menu.d.ts +248 -1
  275. package/types/ojiepermana-angular-component-editor.d.ts +135 -1
  276. package/types/ojiepermana-angular-component-empty.d.ts +50 -1
  277. package/types/ojiepermana-angular-component-form.d.ts +159 -1
  278. package/types/ojiepermana-angular-component-hover-card.d.ts +75 -1
  279. package/types/ojiepermana-angular-component-icon.d.ts +89 -1
  280. package/types/ojiepermana-angular-component-input-group.d.ts +51 -1
  281. package/types/ojiepermana-angular-component-input-otp.d.ts +155 -1
  282. package/types/ojiepermana-angular-component-input.d.ts +21 -1
  283. package/types/ojiepermana-angular-component-item.d.ts +93 -1
  284. package/types/ojiepermana-angular-component-kanban.d.ts +70 -1
  285. package/types/ojiepermana-angular-component-kbd.d.ts +16 -1
  286. package/types/ojiepermana-angular-component-label.d.ts +11 -1
  287. package/types/ojiepermana-angular-component-menubar.d.ts +93 -1
  288. package/types/ojiepermana-angular-component-native-select.d.ts +26 -1
  289. package/types/ojiepermana-angular-component-navigation-menu.d.ts +104 -1
  290. package/types/ojiepermana-angular-component-pagination.d.ts +33 -1
  291. package/types/ojiepermana-angular-component-pillbox.d.ts +222 -1
  292. package/types/ojiepermana-angular-component-popover.d.ts +66 -1
  293. package/types/ojiepermana-angular-component-progress.d.ts +17 -1
  294. package/types/ojiepermana-angular-component-radio.d.ts +60 -1
  295. package/types/ojiepermana-angular-component-resizable.d.ts +117 -1
  296. package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -1
  297. package/types/ojiepermana-angular-component-segmented-control.d.ts +58 -1
  298. package/types/ojiepermana-angular-component-select.d.ts +122 -1
  299. package/types/ojiepermana-angular-component-separator.d.ts +14 -1
  300. package/types/ojiepermana-angular-component-sheet.d.ts +130 -1
  301. package/types/ojiepermana-angular-component-skeleton.d.ts +10 -1
  302. package/types/ojiepermana-angular-component-slider.d.ts +83 -1
  303. package/types/ojiepermana-angular-component-spinner.d.ts +13 -1
  304. package/types/ojiepermana-angular-component-switch.d.ts +44 -1
  305. package/types/ojiepermana-angular-component-table.d.ts +57 -1
  306. package/types/ojiepermana-angular-component-tabs.d.ts +124 -1
  307. package/types/ojiepermana-angular-component-textarea.d.ts +17 -1
  308. package/types/ojiepermana-angular-component-timeline.d.ts +64 -1
  309. package/types/ojiepermana-angular-component-toast.d.ts +64 -1
  310. package/types/ojiepermana-angular-component-toggle-group.d.ts +90 -1
  311. package/types/ojiepermana-angular-component-toggle.d.ts +25 -1
  312. package/types/ojiepermana-angular-component-tooltip.d.ts +143 -1
  313. package/types/ojiepermana-angular-component-utils-core.d.ts +184 -1
  314. package/types/ojiepermana-angular-component-utils-overlay.d.ts +21 -1
  315. package/types/ojiepermana-angular-component-utils-scale.d.ts +19 -1
  316. package/types/ojiepermana-angular-component-utils.d.ts +2 -1
  317. package/types/ojiepermana-angular-component.d.ts +2 -1
  318. package/types/ojiepermana-angular-navigation-core.d.ts +59 -1
  319. package/types/ojiepermana-angular-navigation-icon.d.ts +12 -1
  320. package/types/ojiepermana-angular-navigation-service.d.ts +116 -1
  321. package/types/ojiepermana-angular-navigation-types.d.ts +144 -1
  322. package/types/ojiepermana-angular-navigation.d.ts +507 -1
  323. package/types/ojiepermana-angular-sdk.d.ts +89 -1
  324. package/types/ojiepermana-angular-theme-component-settings.d.ts +154 -1
  325. package/types/ojiepermana-angular-theme-layout-services.d.ts +147 -1
  326. package/types/ojiepermana-angular-theme-layout-types.d.ts +40 -1
  327. package/types/ojiepermana-angular-theme-layout-wrapper.d.ts +299 -1
  328. package/types/ojiepermana-angular-theme-layout.d.ts +129 -1
  329. package/types/ojiepermana-angular-theme-page-core.d.ts +157 -1
  330. package/types/ojiepermana-angular-theme-page-filter.d.ts +77 -1
  331. package/types/ojiepermana-angular-theme-page-root.d.ts +88 -1
  332. package/types/ojiepermana-angular-theme-page-side.d.ts +50 -1
  333. package/types/ojiepermana-angular-theme-page-slots.d.ts +40 -1
  334. package/types/ojiepermana-angular-theme-page.d.ts +5 -1
  335. package/types/ojiepermana-angular-theme-shell-services.d.ts +193 -1
  336. package/types/ojiepermana-angular-theme-shell-types.d.ts +105 -1
  337. package/types/ojiepermana-angular-theme-shell.d.ts +100 -1
  338. package/types/ojiepermana-angular-theme-styles.d.ts +319 -1
  339. package/types/ojiepermana-angular-theme.d.ts +2 -1
  340. package/types/ojiepermana-angular.d.ts +5 -5
@@ -0,0 +1,340 @@
1
+ # @ojiepermana/angular/theme/shell
2
+
3
+ The application shell root. Where `@ojiepermana/angular/theme/layout` arranges an
4
+ app _inside_ a page, `shell` owns the whole surface — a browser tab, an **OS
5
+ window**, a tablet, a phone — and bridges it to Tauri (or Electron, or any other
6
+ desktop runtime).
7
+
8
+ A `<Shell>` holds the app directly, plus a titlebar it renders itself when there
9
+ is window chrome to draw:
10
+
11
+ ```html
12
+ <Shell mode="desktop" device="macos" color="sync">
13
+ <button shellBarStart type="button">Menu</button>
14
+ <span shellBarTitle>Acme Studio</span>
15
+ <app-sync-badge shellBarEnd />
16
+
17
+ <Layout>
18
+ <LayoutVertical>
19
+ <LayoutNavigation><Navigation … /></LayoutNavigation>
20
+ <LayoutContent><router-outlet /></LayoutContent>
21
+ </LayoutVertical>
22
+ </Layout>
23
+ </Shell>
24
+ ```
25
+
26
+ `<Layout>` is a direct child — there is no container element. Inside a shell it
27
+ grows into whatever the titlebar left over (`--layout-viewport-height` becomes
28
+ `auto` plus a zero flex-basis) instead of measuring the viewport and overflowing
29
+ by the height of the bar.
30
+
31
+ ## Entry points
32
+
33
+ ```ts
34
+ import {
35
+ ShellComponent,
36
+ ShellService,
37
+ provideShellWindowBridge,
38
+ provideTauriShellWindowBridge,
39
+ isTauriRuntime,
40
+ type ShellMode,
41
+ type ShellDevice,
42
+ type ShellWindowBridge,
43
+ } from '@ojiepermana/angular/theme/shell';
44
+ ```
45
+
46
+ The secondary entry points stay available for explicit imports:
47
+
48
+ ```ts
49
+ import { ShellService } from '@ojiepermana/angular/theme/shell/services';
50
+ import { SHELL_MODES, SHELL_MODE_DEVICES } from '@ojiepermana/angular/theme/shell/types';
51
+ ```
52
+
53
+ `ShellBarComponent` is deliberately **not** exported. When a titlebar exists is
54
+ `<Shell>`'s decision, not the consumer's — configure it through `<Shell>` and its
55
+ slots.
56
+
57
+ ## The four axes
58
+
59
+ | Input | Values | Storage key |
60
+ | -------- | ---------------------------------------------------------------- | -------------- |
61
+ | `mode` | `web`, `desktop`, `tablet`, `mobile` | `shell-mode` |
62
+ | `device` | `browser`, `macos`, `windows`, `linux`, `ipad`, `android`, `ios` | `shell-device` |
63
+ | `color` | `sync`, `default` | `shell-color` |
64
+ | `frame` | `classic`, `modern` | `shell-frame` |
65
+
66
+ Every axis is optional and falls back rather than demanding a value:
67
+
68
+ - **`mode`** — the input, else the stored `shell-mode`, else `desktop` when a
69
+ desktop runtime is registered (a Tauri window _is_ a desktop shell), else `web`.
70
+ - **`device`** — the input, else the stored `shell-device`, else whatever the
71
+ window bridge reports, else the mode's default device.
72
+ - **`color`** — the input, else the stored `shell-color`, else `sync`.
73
+ - **`frame`** — the input, else the stored `shell-frame`, else `classic`; only
74
+ `desktop` can be `modern`.
75
+
76
+ ### Driving the axes from localStorage
77
+
78
+ Because all four are storage-backed, a delivery target can be flipped **without a
79
+ rebuild** — useful for trying a native look, or for reproducing a tablet report on
80
+ a desktop machine. Set the keys and reload:
81
+
82
+ ```js
83
+ localStorage.setItem('shell-mode', 'desktop');
84
+ localStorage.setItem('shell-device', 'macos');
85
+ localStorage.setItem('shell-color', 'default');
86
+ localStorage.setItem('shell-frame', 'modern');
87
+ ```
88
+
89
+ An unrecognized value is ignored rather than throwing, so a stale or hand-typo'd
90
+ key degrades to the axis default.
91
+
92
+ At runtime, go through `ShellService` — each setter writes its own key:
93
+
94
+ ```ts
95
+ const shell = inject(ShellService);
96
+
97
+ shell.setMode('desktop'); // a user choice — persists to shell-mode
98
+ shell.setDevice('macos'); // …to shell-device
99
+ shell.setColor('default'); // …to shell-color
100
+ shell.setFrame('modern'); // …to shell-frame
101
+
102
+ shell.registerMode('desktop'); // a default — yields to a stored choice
103
+ ```
104
+
105
+ Pass `{ persist: false }` to any setter to change the axis for this session only.
106
+
107
+ Inputs, by contrast, are **host declarations, not user preferences**: they outrank
108
+ storage and never write to it, so `<Shell mode="desktop">` in a Tauri build cannot
109
+ be knocked over by a stale key — and pinning an input does not destroy the choice
110
+ underneath it.
111
+
112
+ ### Modes and their devices
113
+
114
+ | Mode | Devices | Chrome |
115
+ | --------- | --------------------------- | -------------------------- |
116
+ | `web` | `browser` | none — the browser drew it |
117
+ | `desktop` | `macos`, `windows`, `linux` | its own titlebar |
118
+ | `tablet` | `ipad`, `android` | none |
119
+ | `mobile` | `ios`, `android` | none |
120
+
121
+ `android` deliberately belongs to both `tablet` and `mobile`: the same OS ships on
122
+ both form factors, and only `mode` can tell them apart.
123
+
124
+ `mode` and `device` are always resolved as a **coherent pair**. A device belonging
125
+ to another form factor (`mode="desktop" device="ipad"`) is corrected to the mode's
126
+ default, so `data-shell-device` never describes something the mode cannot be. The
127
+ stored preference itself is left alone, so a temporary `mode="web"` does not erase
128
+ a stored `macos`.
129
+
130
+ ### Mode locks the layout width
131
+
132
+ `mode` is the one axis that constrains another package. On `desktop`, `tablet`, and
133
+ `mobile` the app _is_ the surface, so there is no page for the layout frame to be
134
+ inset within — `LayoutService.widthLocked()` becomes `true` and `width()` reports
135
+ `full`, outranking even `<Layout>`'s own `width` input.
136
+
137
+ The user's choice is not destroyed: it stays in `LayoutService.preferredWidth()` (and
138
+ in `localStorage`), so returning to `web` restores it. `ThemeSettings` reflects this
139
+ by disabling every width but `full` and explaining why.
140
+
141
+ Switch the axes at runtime through `ThemeSettings`
142
+ (`@ojiepermana/angular/theme/component/settings`), which exposes all four in a
143
+ **Shell** section directly below Theme.
144
+
145
+ ## Chrome color
146
+
147
+ `color="sync"` (the default) promotes the selected **Theme color** to the shell
148
+ background through `--primary`. Its title and controls use `--primary-foreground`,
149
+ so named accents and the consumer's `brand` color keep the same readable semantic
150
+ pair in light and dark modes.
151
+
152
+ `color="default"` paints the native chrome of the active `device` instead — for an
153
+ app that wants to disappear into its OS. Each desktop device has a light and dark
154
+ palette, applied through `--shell-bar-background` / `-foreground` / `-border`
155
+ under `[data-shell-color='default'][data-shell-device='…']`.
156
+
157
+ ## Frame
158
+
159
+ `frame` decides how the app sits inside its window. Only a desktop window has a
160
+ frame to shape, so this collapses to `classic` on every other mode.
161
+
162
+ **`classic`** (the default) is the traditional desktop arrangement: the app is flush
163
+ to the window edge, with a bordered titlebar stacked on top of it.
164
+
165
+ **`modern`** insets the app instead. It gains `mx-3 mb-3 mt-0`
166
+ (`--shell-frame-inset`, which rides `--spacing-base`), so it floats as a panel free
167
+ of the window on three sides and meets the titlebar on the fourth. The titlebar then
168
+ drops its bottom border and takes the **same background token as the surround**, so
169
+ the bar and the margin around the panel read as one continuous frame rather than two
170
+ stacked surfaces.
171
+
172
+ The inset is margin on the layout, never padding on `<Shell>`: the titlebar is the
173
+ shell's other flex child, and padding would indent it too, breaking the full-bleed
174
+ drag region and pulling the macOS traffic lights off the window corner. The margin
175
+ also releases the layout's width — while it kept `width: 100%` the margins only
176
+ _shifted_ a full-width panel, overflowing the trailing edge into the shell's
177
+ `overflow-hidden` and leaving a gap on the leading side alone.
178
+
179
+ ### Panel edge
180
+
181
+ Inside a desktop window the app gets a panel edge: `modern` is rounded to
182
+ `--shell-frame-radius` (**12px**) and outlined 1px in `--shell-frame-border`, the
183
+ full-strength structural border tier.
184
+
185
+ `modern` rounds and closes all four sides, since it is a free-floating panel — its
186
+ titlebar drops the divider, so the panel's own top edge is what closes it. `classic`
187
+ keeps the entire layout square and flush to the window edge. Its top edge meets the
188
+ titlebar, which already draws that seam with its own `border-b`; outlining it again
189
+ would double the line, and rounding any edge would cut notches of chrome into the
190
+ full-bleed window join. No other mode has a window to shape.
191
+
192
+ The radius is a fixed 12px rather than riding `--radius-base`: this is window
193
+ geometry, matching what the OS rounds its own windows to, not a component-styling
194
+ choice the `theme-radius` axis should retune.
195
+
196
+ On `color="sync"`, the bar and surround both use the active `--primary`, while the
197
+ inset app panel remains on `--background`; the selected Theme color therefore makes
198
+ the frame visible without introducing another palette. `color="default"` keeps the
199
+ same composition but uses the active device's native chrome instead.
200
+
201
+ ## Window buttons
202
+
203
+ Buttons follow the **device**, not the runtime:
204
+
205
+ | Device | Controls |
206
+ | ----------------- | ------------------------------------------------------------------------- |
207
+ | `macos` | traffic lights on the **leading** edge — close, minimize, zoom |
208
+ | `windows`/`linux` | square glyph buttons on the **trailing** edge — minimize, maximize, close |
209
+
210
+ The macOS lights are drawn by the shell, not the OS. That is deliberate: a
211
+ `decorations: false` window has no OS buttons at all, so without them the window
212
+ could not be closed. Their fills are macOS's own constants rather than theme tokens
213
+ — a traffic light that recoloured with the accent would stop reading as one — and
214
+ each is a real button with an `aria-label`, so colour is never the only way to tell
215
+ them apart.
216
+
217
+ They sit at `--shell-traffic-light-size` (~13.1px), a little over the 12px the OS
218
+ draws: the app's own lights are in a titlebar the user can mis-click, so they get a
219
+ slightly larger target. Each takes a `cursor: pointer`, and on hover it darkens to
220
+ its **own** pressed shade — the per-light shift macOS uses, so the feedback reads as
221
+ "this specific control" rather than a generic highlight. The glyph inside appears on
222
+ hover and on keyboard focus, so the hover state never rests on colour alone.
223
+
224
+ Set `nativeWindowControls` when the runtime still draws its own decorations — Tauri's
225
+ macOS `titleBarStyle: 'Overlay'`. macOS then reserves `--shell-traffic-light-inset`
226
+ on the leading edge for the OS lights and draws none of its own; Windows and Linux
227
+ draw nothing either.
228
+
229
+ Whether those buttons _do_ anything is the bridge's business; the shape of the
230
+ chrome is the device's. Every button carries an `aria-label` (`minimizeLabel`,
231
+ `maximizeLabel`, `restoreLabel`, `closeLabel` are `<Shell>` inputs, for
232
+ localization), and the maximize/zoom button reports `aria-pressed` so the maximized
233
+ state is announced.
234
+
235
+ ## Desktop navigation flyout
236
+
237
+ When `LayoutWrapperDefault` uses `nav-type="desktop"`, it publishes its primary
238
+ navigation data to the titlebar instead of rendering a second navigation region
239
+ inside the layout. `<Shell>` then adds the same icon-only `NavigationFlyout`
240
+ pattern used by an empty-layout `<Page>`, adapted to desktop chrome as a
241
+ window-width popover:
242
+
243
+ - macOS — after consumer `[shellBarEnd]` content, at the far right opposite the
244
+ traffic lights;
245
+ - Windows and Linux — before consumer `[shellBarStart]` content, at the far left
246
+ opposite the window controls.
247
+
248
+ The trigger is rendered only when desktop navigation data exists. It keeps a real
249
+ button, `aria-haspopup="menu"`, an explicit accessible name, visible keyboard
250
+ focus, and the established semantic shell/navigation tokens. Its surface stays
251
+ transparent, including hover and open states, while the icon inherits the exact
252
+ `--shell-bar-foreground` color used by the titlebar text. The open panel is fixed
253
+ at the viewport origin (`top: 0; left: 0`) and spans the full window width instead
254
+ of using a fixed content cap. Its lower corners use the desktop-only
255
+ `--shell-frame-radius` while the upper edge stays square like the classic window
256
+ frame. Set
257
+ `[navigationFlyout]="false"` to suppress it, or localize/customize it through
258
+ `navigationFlyoutLabel` and `navigationFlyoutIcon`.
259
+
260
+ ## Window dragging
261
+
262
+ Declarative, so nothing runs on pointer-down. In desktop mode `<Shell>` becomes
263
+ Electron's ancestor `shell-drag-region` (`-webkit-app-region: drag`) and paints a
264
+ transparent Tauri frame layer at `z-index: 0` with `data-tauri-drag-region`. The
265
+ titlebar also carries the direct Tauri marker; it deliberately does not create a
266
+ second Electron drag rectangle above the flyout.
267
+
268
+ Application foregrounds such as `<Layout>` sit at `z-index: 10` and opt out through
269
+ `app-region: no-drag`; the titlebar sits at `z-index: 20`, and its open flyout
270
+ panel stays at `z-index: 50` with an explicit no-drag region. Consequently the
271
+ exposed window surround—including the modern-frame gaps—moves the window, while
272
+ buttons, fields, routed content, and every flyout menu item keep normal pointer
273
+ interaction. Electron's ancestor drag region is suspended while the flyout is
274
+ mounted because native app-region hit testing is independent of ordinary DOM
275
+ stacking; it resumes automatically as soon as the panel closes.
276
+
277
+ Turn the bar into pure UI with `[drag]="false"`. Runtimes that need an explicit
278
+ call can use `ShellService.startDragging()`. Disabling drag removes both the
279
+ frame-wide layer and the titlebar markers.
280
+
281
+ ## Bridging to Tauri
282
+
283
+ The theme package never imports a desktop SDK. Everything the shell needs from a
284
+ window sits behind `ShellWindowBridge`, so a browser build pays nothing.
285
+
286
+ For a Tauri app with `app.withGlobalTauri = true`:
287
+
288
+ ```ts
289
+ import { provideTauriShellWindowBridge } from '@ojiepermana/angular/theme/shell';
290
+
291
+ export const appConfig: ApplicationConfig = {
292
+ // The bridge reports the OS, so mode and device both resolve on their own.
293
+ providers: [provideTauriShellWindowBridge()],
294
+ };
295
+ ```
296
+
297
+ Without the global, hand it the modules instead — they stay dynamic imports, so a
298
+ web build never pulls them in:
299
+
300
+ ```ts
301
+ provideTauriShellWindowBridge({
302
+ currentWindow: () => import('@tauri-apps/api/window').then((m) => m.getCurrentWindow()),
303
+ platform: () => import('@tauri-apps/plugin-os').then((m) => m.platform()),
304
+ });
305
+ ```
306
+
307
+ This is safe to register unconditionally: outside a Tauri webview the bridge
308
+ resolves no window and every command becomes a no-op. Use `isTauriRuntime()` if you
309
+ need to branch yourself.
310
+
311
+ For any other runtime, implement `ShellWindowBridge` and register it with
312
+ `provideShellWindowBridge()`. With no bridge at all, `ShellService` falls back to an
313
+ inert web bridge — which is what keeps `<Shell>` renderable in a browser tab, in a
314
+ unit test, and under SSR.
315
+
316
+ ## Tokens
317
+
318
+ Geometry rides `--spacing-base`, so window chrome tracks the `theme-space` density
319
+ axis:
320
+
321
+ | Token | Purpose |
322
+ | ----------------------------- | ---------------------------------------------- |
323
+ | `--shell-bar-height` | Titlebar thickness — the single geometry knob. |
324
+ | `--shell-bar-inline` | Titlebar inline padding. |
325
+ | `--shell-bar-gap` | Gap between items in the titlebar. |
326
+ | `--shell-control-size` | Window button hit area. |
327
+ | `--shell-traffic-light-inset` | Leading run reserved for macOS traffic lights. |
328
+ | `--shell-traffic-light-size` | Diameter of one traffic light (~13.1px). |
329
+ | `--shell-bar-background` | Shell chrome background; see **Chrome color**. |
330
+ | `--shell-bar-foreground` | Titlebar text and glyphs. |
331
+ | `--shell-bar-border` | Titlebar bottom divider (`classic` only). |
332
+ | `--shell-frame-inset` | `modern`: gap between the app and the window. |
333
+ | `--shell-frame-radius` | Corner radius of the app in a desktop window. |
334
+
335
+ ## Host attributes
336
+
337
+ `<Shell>` reflects its resolved state so consumer CSS and tests can key off it:
338
+ `data-shell-root`, `data-shell-mode`, `data-shell-device`, `data-shell-color`,
339
+ `data-shell-platform`, `data-shell-window`. The titlebar adds
340
+ `data-shell-focused` — an unfocused window recedes, per OS convention.
@@ -0,0 +1,178 @@
1
+ # Theme
2
+
3
+ `@ojiepermana/angular/theme/styles` menyediakan provider untuk mode, warna (accent +
4
+ neutral, gaya FluxUI), brand color, dan preload aset tema global.
5
+
6
+ ```ts
7
+ import { provideUiTheme } from '@ojiepermana/angular/theme/styles';
8
+
9
+ export const appConfig = {
10
+ providers: [
11
+ provideUiTheme({
12
+ mode: 'light',
13
+ color: 'base', // accent: base, red…rose, brand
14
+ neutral: 'base', // gray family: base, slate, gray, zinc, …
15
+ radius: 'md', // corner radius: none, xs, sm, md, xl, full
16
+ space: 'normal', // spacing density: compact, normal
17
+ brand: '221 83% 53%', // warna brand consumer (HSL triplet, atau { color, foreground })
18
+ }),
19
+ ],
20
+ };
21
+ ```
22
+
23
+ ## API Notes
24
+
25
+ - `mode` mem-bootstrap `ThemeModeService` dan default mode yang disimpan di storage.
26
+ - `color` mem-bootstrap `ThemeColorService`; accent palette awal (`<html theme-color>`).
27
+ - `neutral` keluarga neutral awal (`<html theme-neutral>`); berkomposisi dengan accent.
28
+ - `radius` mem-bootstrap `ThemeRadiusService`; preset corner radius awal (`<html theme-radius>`).
29
+ Menggerakkan knob `--radius-base` sehingga seluruh skala `--radius-*` dan utility `rounded-*` ikut.
30
+ Nilainya mengikuti Tailwind: `none`, `xs`, `sm`, `md` (default), `xl`, dan `full`.
31
+ - `space` mem-bootstrap `ThemeSpaceService`; preset spacing density awal (`<html theme-space>`).
32
+ Menggerakkan knob `--spacing-base` sehingga setiap utility `p-*`/`m-*`/`gap-*`/`w-*`/`h-*` ikut.
33
+ - `brand` mem-bootstrap `ThemeBrandService`; set `--brand` / utility `bg-brand` dan preset
34
+ accent `theme-color='brand'`. Menerima string HSL triplet atau `{ color, foreground }`.
35
+ Bisa diubah runtime via `setBrand()`, persist di storage.
36
+ - `icons.materialSymbols` mengontrol preload stylesheet Material Symbols pada bootstrap aplikasi.
37
+ - Pilihan yang dipersist (`theme-color` / `theme-neutral` / `theme-radius` / `theme-space` /
38
+ `theme-brand`) menang atas default.
39
+
40
+ ## Default Behavior
41
+
42
+ - Material Symbols **tidak** di-preload secara default (opt-in). Tanpa konfigurasi,
43
+ `provideUiTheme()` tidak melakukan request jaringan eksternal apa pun — ramah privasi,
44
+ offline, dan CSP.
45
+ - Untuk mengaktifkan preload font dari Google Fonts, set `icons.materialSymbols` ke `true`,
46
+ atau self-host font Material Symbols dan `@import` sendiri di stylesheet Anda.
47
+ - Jika memakai `@ojiepermana/angular/component/icon` tanpa provider tema, aktifkan
48
+ `provideMaterialSymbols()` dari entrypoint icon atau self-host stylesheet font sendiri.
49
+
50
+ ## Token Semantik Status
51
+
52
+ Selain palet accent dan neutral, tema mengemit tiga token status semantik beserta
53
+ pasangan foregroundnya. Semuanya digenerate oleh `scripts/gen-theme-colors.mjs` ke
54
+ `css/base/status.css`, jadi jangan diedit tangan.
55
+
56
+ | Token | Pasangan foreground | Seed | Dipakai oleh |
57
+ | ----------- | ---------------------- | ----------- | ------------------------------------ |
58
+ | `--success` | `--success-foreground` | green (142) | `bg-success text-success-foreground` |
59
+ | `--warning` | `--warning-foreground` | amber (38) | `bg-warning text-warning-foreground` |
60
+ | `--info` | `--info-foreground` | sky (199) | `bg-info text-info-foreground` |
61
+
62
+ `--destructive` tetap ditulis tangan di `css/base/theme.css` karena tidak berasal
63
+ dari seed accent, tapi generator ikut memvalidasi kontrasnya.
64
+
65
+ ## Jaminan Kontras
66
+
67
+ Generator mengukur kontras setiap pasangan token teks yang diemitnya dengan rumus
68
+ WCAG, bukan menebak dari rentang hue. Aturannya:
69
+
70
+ - pasangan teks (`primary`, `accent`, `secondary`, `muted`, `surface`, `card`,
71
+ `popover`, dan `foreground` terhadap `background`) wajib minimal 4.5 banding 1;
72
+ - `--ring` diemit terpisah dari `--primary` dan wajib minimal 3 banding 1 terhadap
73
+ `--background`, jadi indikator fokus selalu terlihat;
74
+ - foreground yang meleset digeser lightnessnya sekecil mungkin sampai lolos. Hue dan
75
+ saturation tidak pernah bergeser, sehingga identitas warna palet tetap;
76
+ - bila tidak ada nilai yang bisa lolos, generator gagal dan tidak menulis apa pun.
77
+
78
+ A brand the consumer picks at runtime is held to the same rules, and split the
79
+ same way. `ThemeBrandService.setBrand()` measures it with the same WCAG formula
80
+ (`theme-contrast.ts`, a port of `scripts/theme-contrast.mjs`) before storing it:
81
+
82
+ - `--brand` itself is never moved. Like a generated `--primary`, the fill keeps
83
+ the lightness it was chosen with, so `theme-color='brand'` ships the colour the
84
+ consumer asked for;
85
+ - `--brand-foreground` is moved until text on the brand clears 4.5 to 1;
86
+ - the focus ring is solved separately, once per mode, into `--brand-ring-light`
87
+ and `--brand-ring-dark`. `css/color/brand.css` maps `--ring` to
88
+ `var(--brand-ring, var(--brand))` and picks the right one per `data-mode`, so
89
+ the ring clears 3 to 1 against that mode's `--background` without dragging the
90
+ fill down with it.
91
+
92
+ Every HSL form CSS accepts is normalised first — space or comma separated, a hue
93
+ written with `deg`/`grad`/`rad`/`turn`, a hue outside 0..360 — so none of them can
94
+ paint while skipping the measurement. Hex is accepted and converted too, since
95
+ that is what a native colour picker returns. A value with nothing to measure in
96
+ it (`var(--consumer-brand)`, say) is passed through as given, and forfeits the
97
+ guarantee.
98
+
99
+ Jalankan `node scripts/gen-theme-colors.mjs --check` untuk memastikan CSS yang
100
+ ter commit masih cocok dengan seed. Cek ini juga berjalan di `verify:libs` dan CI.
101
+
102
+ ## Standar Token Geometri
103
+
104
+ Setiap nilai geometri di `library/` wajib turun dari token tema, bukan angka mati.
105
+ Aturan ini yang membuat sumbu `theme-space` dan `theme-radius` benar benar
106
+ menjangkau seluruh library, bukan hanya komponen yang kebetulan memakai utility
107
+ Tailwind. Keputusan lengkapnya di
108
+ [spec 0003](../../../docs/specs/0003-jangkauan-sumbu-space-radius/index.md).
109
+
110
+ **Pola kanonik**:
111
+
112
+ ```css
113
+ /* Jarak di CSS komponen: selalu turun dari unit spacing */
114
+ .panel {
115
+ padding: calc(var(--spacing-base) * 3);
116
+ gap: calc(var(--spacing-base) * 2);
117
+ }
118
+
119
+ /* Sudut: pakai skala radius */
120
+ .panel {
121
+ border-radius: var(--radius-md);
122
+ }
123
+ ```
124
+
125
+ ```html
126
+ <!-- Template: pakai skala utility, yang sudah turun dari --spacing -->
127
+ <div class="gap-2 p-3">
128
+ <!-- Sudut -->
129
+ <div class="rounded-md">
130
+ <!-- Tinggi kontrol: satu knop bernama, bukan literal tinggi -->
131
+ <button class="h-control-md"></button>
132
+ </div>
133
+ </div>
134
+ ```
135
+
136
+ **Jangkauan sumbu**: jarak (padding, margin, gap, ukuran) plus tinggi kontrol ikut
137
+ `theme-space`. Tipografi, ukuran ikon, dan tebal garis **tidak** ikut. Bentuk pil
138
+ semantik (`rounded-full` pada avatar, switch, radio, progress, spinner, dan track
139
+ slider) dikunci sebagai bentuk, jadi sumbu radius tidak menyentuhnya.
140
+
141
+ **Penegakan**: `node scripts/check-geometry-tokens.mjs` (`bun run check:libs:geometry`)
142
+ memindai `library/**/*.ts` dan `library/**/*.css`, lalu menggagalkan build saat
143
+ menemukan pelanggaran. Cek ini berjalan di `verify:libs` dan di CI pada tiap PR dan
144
+ push ke `main`. Yang ditolak:
145
+
146
+ | Jenis | Ditolak | Contoh |
147
+ | -------------- | -------------------------------------------------------------------------------- | --------------------- |
148
+ | Panjang | properti jarak dan ukuran dengan nilai `px`, `rem`, atau `em` mentah | `padding: 12px` |
149
+ | Radius | `border-radius` dengan panjang mentah | `border-radius: 10px` |
150
+ | Nilai arbitrer | utility jarak, ukuran, dan `rounded-*` yang kurung sikunya berisi panjang mentah | `min-w-[8rem]` |
151
+
152
+ Yang **tidak** ditolak, dan memang begitu adanya:
153
+
154
+ - nilai yang membaca token, termasuk `calc(var(--spacing-base) * 3)`,
155
+ `rounded-[var(--radius-base)]`, dan `rounded-[inherit]`;
156
+ - `border-radius: inherit` serta kata kunci tanpa besaran seperti `auto` dan `fit-content`;
157
+ - `0` dan persen, karena keduanya bukan besaran yang punya skala;
158
+ - tebal border dan outline, karena garis rambut tidak boleh ikut skala;
159
+ - ekspresi `calc()`, `min()`, `clamp()` di dalam kurung siku utility, dan satuan
160
+ viewport seperti `85vh`. Guard mempercayainya; kalau isinya ternyata angka mati,
161
+ itu yang lolos dari jaring ini;
162
+ - berkas `*.spec.ts`, karena test hanya mencerminkan class string komponennya. Satu
163
+ nilai diperbaiki di komponennya, bukan di dua tempat;
164
+ - `library/theme/styles/css/` yang justru tempat token didefinisikan.
165
+
166
+ **Pengecualian**: tinggal di
167
+ [`scripts/geometry-token-exceptions.json`](../../../scripts/geometry-token-exceptions.json).
168
+ Tiap baris wajib membawa `pattern`, `files`, dan `reason`; baris tanpa alasan
169
+ tertulis ditolak oleh guard itu sendiri, jadi daftar ini tidak bisa dipakai sebagai
170
+ tempat buang. `wave` bernilai `null` untuk pengecualian permanen, atau angka 2
171
+ sampai 5 untuk utang sementara yang dihapus oleh gelombang itu sendiri. Guard
172
+ mencetak sisa utang per gelombang tiap kali dijalankan, sehingga yang belum
173
+ dibereskan selalu berupa angka, bukan perasaan.
174
+
175
+ **Entry point baru**: tambahkan barisnya ke tabel inventaris sumbu di
176
+ [rationale spec 0003](../../../docs/specs/0003-jangkauan-sumbu-space-radius/rationale.md),
177
+ sebutkan sumbu mana yang berlaku dan seberapa jauh sudah tersambung. Tabel itu
178
+ rujukan tunggal soal sudut mana yang sengaja dikunci dan mana yang kelupaan.