@fortanix/baklava 1.0.0-beta-20241114

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 (454) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +373 -0
  3. package/README.md +43 -0
  4. package/app/Demo.tsx +33 -0
  5. package/app/index.html +12 -0
  6. package/app/lib.ts +54 -0
  7. package/app/main.tsx +32 -0
  8. package/dist/baklava.d.ts +752 -0
  9. package/dist/baklava.js +4962 -0
  10. package/dist/lib.css +1 -0
  11. package/package.json +102 -0
  12. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-100.woff2 +0 -0
  13. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-200.woff2 +0 -0
  14. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-300.woff2 +0 -0
  15. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-500.woff2 +0 -0
  16. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-600.woff2 +0 -0
  17. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-700.woff2 +0 -0
  18. package/src/assets/fonts/montserrat/montserrat-v25-latin_latin-ext-regular.woff2 +0 -0
  19. package/src/assets/fonts/open-sans/open-sans-v23-latin-600.woff2 +0 -0
  20. package/src/assets/fonts/open-sans/open-sans-v23-latin-700.woff2 +0 -0
  21. package/src/assets/fonts/open-sans/open-sans-v23-latin-regular.woff2 +0 -0
  22. package/src/assets/fonts/source-code-pro/source-code-pro-v14-latin-regular.woff2 +0 -0
  23. package/src/assets/icons/_icons.ts +58 -0
  24. package/src/assets/icons/accounts.svg +11 -0
  25. package/src/assets/icons/alert.svg +3 -0
  26. package/src/assets/icons/apache.svg +3 -0
  27. package/src/assets/icons/apps.svg +5 -0
  28. package/src/assets/icons/assessment.svg +11 -0
  29. package/src/assets/icons/audit-log.svg +12 -0
  30. package/src/assets/icons/authentication.svg +12 -0
  31. package/src/assets/icons/calendar.svg +10 -0
  32. package/src/assets/icons/caret-down.svg +3 -0
  33. package/src/assets/icons/check.svg +3 -0
  34. package/src/assets/icons/cloud-accounts.svg +15 -0
  35. package/src/assets/icons/copy.svg +4 -0
  36. package/src/assets/icons/cross.svg +4 -0
  37. package/src/assets/icons/dashboard.svg +12 -0
  38. package/src/assets/icons/dataverse.svg +12 -0
  39. package/src/assets/icons/delete.svg +5 -0
  40. package/src/assets/icons/docs.svg +10 -0
  41. package/src/assets/icons/download.svg +11 -0
  42. package/src/assets/icons/edit-params.svg +3 -0
  43. package/src/assets/icons/edit.svg +10 -0
  44. package/src/assets/icons/email.svg +3 -0
  45. package/src/assets/icons/eye.svg +11 -0
  46. package/src/assets/icons/file-error.svg +17 -0
  47. package/src/assets/icons/file.svg +15 -0
  48. package/src/assets/icons/folder.svg +14 -0
  49. package/src/assets/icons/fortanix-ki.svg +13 -0
  50. package/src/assets/icons/graph.svg +9 -0
  51. package/src/assets/icons/groups.svg +10 -0
  52. package/src/assets/icons/hide.svg +3 -0
  53. package/src/assets/icons/home.svg +11 -0
  54. package/src/assets/icons/iam.svg +11 -0
  55. package/src/assets/icons/info.svg +4 -0
  56. package/src/assets/icons/infrastructure.svg +5 -0
  57. package/src/assets/icons/integrations.svg +3 -0
  58. package/src/assets/icons/key-link.svg +12 -0
  59. package/src/assets/icons/key.svg +4 -0
  60. package/src/assets/icons/no-login.svg +10 -0
  61. package/src/assets/icons/page-forward.svg +4 -0
  62. package/src/assets/icons/plugins.svg +4 -0
  63. package/src/assets/icons/policy.svg +13 -0
  64. package/src/assets/icons/print.svg +11 -0
  65. package/src/assets/icons/scripts.svg +4 -0
  66. package/src/assets/icons/search.svg +3 -0
  67. package/src/assets/icons/security-object.svg +5 -0
  68. package/src/assets/icons/services.svg +10 -0
  69. package/src/assets/icons/settings.svg +12 -0
  70. package/src/assets/icons/solutions.svg +3 -0
  71. package/src/assets/icons/success.svg +3 -0
  72. package/src/assets/icons/tasks.svg +10 -0
  73. package/src/assets/icons/user-profile.svg +3 -0
  74. package/src/assets/icons/user.svg +10 -0
  75. package/src/assets/icons/warning.svg +3 -0
  76. package/src/assets/icons/workflows.svg +11 -0
  77. package/src/assets/icons_new/Accounts.svg +11 -0
  78. package/src/assets/icons_new/Alert.svg +3 -0
  79. package/src/assets/icons_new/Apache.svg +3 -0
  80. package/src/assets/icons_new/Apps.svg +5 -0
  81. package/src/assets/icons_new/Assessment.svg +11 -0
  82. package/src/assets/icons_new/Audit Log.svg +12 -0
  83. package/src/assets/icons_new/Authentication.svg +12 -0
  84. package/src/assets/icons_new/Calendar.svg +10 -0
  85. package/src/assets/icons_new/Carrot Down.svg +3 -0
  86. package/src/assets/icons_new/Cloud Accounts.svg +15 -0
  87. package/src/assets/icons_new/Copy.svg +4 -0
  88. package/src/assets/icons_new/Dashboard.svg +12 -0
  89. package/src/assets/icons_new/Dataverse.svg +12 -0
  90. package/src/assets/icons_new/Delete.svg +5 -0
  91. package/src/assets/icons_new/Docs.svg +10 -0
  92. package/src/assets/icons_new/Download.svg +11 -0
  93. package/src/assets/icons_new/Edit Params.svg +3 -0
  94. package/src/assets/icons_new/Edit.svg +10 -0
  95. package/src/assets/icons_new/Email.svg +3 -0
  96. package/src/assets/icons_new/Eye.svg +11 -0
  97. package/src/assets/icons_new/Groups.svg +10 -0
  98. package/src/assets/icons_new/Hide.svg +3 -0
  99. package/src/assets/icons_new/Home.svg +11 -0
  100. package/src/assets/icons_new/IAM.svg +11 -0
  101. package/src/assets/icons_new/Info.svg +4 -0
  102. package/src/assets/icons_new/Infrastructure.svg +5 -0
  103. package/src/assets/icons_new/Integrations.svg +3 -0
  104. package/src/assets/icons_new/KI.svg +13 -0
  105. package/src/assets/icons_new/Key Link.svg +12 -0
  106. package/src/assets/icons_new/Key.svg +4 -0
  107. package/src/assets/icons_new/No Login.svg +10 -0
  108. package/src/assets/icons_new/Page FWD.svg +4 -0
  109. package/src/assets/icons_new/Plugins.svg +4 -0
  110. package/src/assets/icons_new/Policy.svg +13 -0
  111. package/src/assets/icons_new/Print.svg +11 -0
  112. package/src/assets/icons_new/Scripts.svg +4 -0
  113. package/src/assets/icons_new/Search.svg +3 -0
  114. package/src/assets/icons_new/Security Objects.svg +5 -0
  115. package/src/assets/icons_new/Services.svg +10 -0
  116. package/src/assets/icons_new/Settings.svg +12 -0
  117. package/src/assets/icons_new/Solutions.svg +3 -0
  118. package/src/assets/icons_new/Tasks.svg +10 -0
  119. package/src/assets/icons_new/User Account.svg +3 -0
  120. package/src/assets/icons_new/Users.svg +10 -0
  121. package/src/assets/icons_new/Workflows.svg +11 -0
  122. package/src/assets/icons_old/_icons.ts +172 -0
  123. package/src/assets/icons_old/account.svg +4 -0
  124. package/src/assets/icons_old/accounts.svg +4 -0
  125. package/src/assets/icons_old/add.svg +4 -0
  126. package/src/assets/icons_old/alert.svg +4 -0
  127. package/src/assets/icons_old/app.svg +4 -0
  128. package/src/assets/icons_old/arrow-drop-down.svg +4 -0
  129. package/src/assets/icons_old/arrow-drop-up.svg +4 -0
  130. package/src/assets/icons_old/arrow-expand.svg +4 -0
  131. package/src/assets/icons_old/arrow-left.svg +5 -0
  132. package/src/assets/icons_old/arrow-right.svg +4 -0
  133. package/src/assets/icons_old/audit-log.svg +4 -0
  134. package/src/assets/icons_old/bell.svg +4 -0
  135. package/src/assets/icons_old/billing.svg +4 -0
  136. package/src/assets/icons_old/bug.svg +4 -0
  137. package/src/assets/icons_old/builds.svg +4 -0
  138. package/src/assets/icons_old/calendar.svg +4 -0
  139. package/src/assets/icons_old/certificate.svg +4 -0
  140. package/src/assets/icons_old/check.svg +4 -0
  141. package/src/assets/icons_old/checkbox-checked.svg +4 -0
  142. package/src/assets/icons_old/checkbox-disabled.svg +4 -0
  143. package/src/assets/icons_old/checkbox-unchecked.svg +4 -0
  144. package/src/assets/icons_old/chevron-left.svg +4 -0
  145. package/src/assets/icons_old/chevron-right.svg +4 -0
  146. package/src/assets/icons_old/clear-all.svg +4 -0
  147. package/src/assets/icons_old/color-picker.svg +10 -0
  148. package/src/assets/icons_old/connection.svg +4 -0
  149. package/src/assets/icons_old/copy.svg +4 -0
  150. package/src/assets/icons_old/cross-thin.svg +4 -0
  151. package/src/assets/icons_old/cross.svg +4 -0
  152. package/src/assets/icons_old/crypto-policy.svg +4 -0
  153. package/src/assets/icons_old/customers.svg +4 -0
  154. package/src/assets/icons_old/dashboard.svg +4 -0
  155. package/src/assets/icons_old/data-center.svg +4 -0
  156. package/src/assets/icons_old/data-connector-read.svg +6 -0
  157. package/src/assets/icons_old/data-connector-write.svg +6 -0
  158. package/src/assets/icons_old/dataset.svg +3 -0
  159. package/src/assets/icons_old/dataverse.svg +6 -0
  160. package/src/assets/icons_old/delete.svg +4 -0
  161. package/src/assets/icons_old/deployment-deployed.svg +4 -0
  162. package/src/assets/icons_old/deployment-none.svg +4 -0
  163. package/src/assets/icons_old/derive.svg +4 -0
  164. package/src/assets/icons_old/docs.svg +4 -0
  165. package/src/assets/icons_old/document-blank.svg +4 -0
  166. package/src/assets/icons_old/domain.svg +4 -0
  167. package/src/assets/icons_old/download-cloud.svg +4 -0
  168. package/src/assets/icons_old/download.svg +4 -0
  169. package/src/assets/icons_old/edit-params.svg +4 -0
  170. package/src/assets/icons_old/edit.svg +4 -0
  171. package/src/assets/icons_old/em-app.svg +4 -0
  172. package/src/assets/icons_old/em-dashboard.svg +4 -0
  173. package/src/assets/icons_old/email.svg +4 -0
  174. package/src/assets/icons_old/empty-credential.svg +4 -0
  175. package/src/assets/icons_old/enterprise-badge.svg +6 -0
  176. package/src/assets/icons_old/environment-production.svg +4 -0
  177. package/src/assets/icons_old/environment-test.svg +4 -0
  178. package/src/assets/icons_old/event-critical.svg +4 -0
  179. package/src/assets/icons_old/event-error.svg +4 -0
  180. package/src/assets/icons_old/event-success.svg +4 -0
  181. package/src/assets/icons_old/event-warning.svg +4 -0
  182. package/src/assets/icons_old/expiration.svg +4 -0
  183. package/src/assets/icons_old/export.svg +4 -0
  184. package/src/assets/icons_old/external.svg +4 -0
  185. package/src/assets/icons_old/eye-closed.svg +4 -0
  186. package/src/assets/icons_old/eye.svg +4 -0
  187. package/src/assets/icons_old/file.svg +7 -0
  188. package/src/assets/icons_old/flag.svg +4 -0
  189. package/src/assets/icons_old/forbid.svg +4 -0
  190. package/src/assets/icons_old/fortanix-app-aci.svg +6 -0
  191. package/src/assets/icons_old/fortanix-app-edp.svg +4 -0
  192. package/src/assets/icons_old/fortanix-app-enclave-os.svg +4 -0
  193. package/src/assets/icons_old/frame-expand.svg +4 -0
  194. package/src/assets/icons_old/fresh.svg +4 -0
  195. package/src/assets/icons_old/generated.svg +4 -0
  196. package/src/assets/icons_old/gift.svg +4 -0
  197. package/src/assets/icons_old/global.svg +4 -0
  198. package/src/assets/icons_old/group.svg +4 -0
  199. package/src/assets/icons_old/help.svg +4 -0
  200. package/src/assets/icons_old/home-info.svg +5 -0
  201. package/src/assets/icons_old/home.svg +4 -0
  202. package/src/assets/icons_old/horizontal-collapse.svg +5 -0
  203. package/src/assets/icons_old/horizontal-expand.svg +5 -0
  204. package/src/assets/icons_old/hsm.svg +4 -0
  205. package/src/assets/icons_old/info.svg +4 -0
  206. package/src/assets/icons_old/install.svg +4 -0
  207. package/src/assets/icons_old/integration.svg +7 -0
  208. package/src/assets/icons_old/key-clone.svg +4 -0
  209. package/src/assets/icons_old/key-custodian-policy.svg +10 -0
  210. package/src/assets/icons_old/key-destroy.svg +4 -0
  211. package/src/assets/icons_old/key-download.svg +4 -0
  212. package/src/assets/icons_old/key-justification-policy.svg +5 -0
  213. package/src/assets/icons_old/key-link.svg +4 -0
  214. package/src/assets/icons_old/key-metadata-policy.svg +5 -0
  215. package/src/assets/icons_old/key-primary.svg +11 -0
  216. package/src/assets/icons_old/key-remove.svg +4 -0
  217. package/src/assets/icons_old/key-rotation.svg +4 -0
  218. package/src/assets/icons_old/key-undo-policy.svg +10 -0
  219. package/src/assets/icons_old/key-wrapping.svg +6 -0
  220. package/src/assets/icons_old/key.svg +4 -0
  221. package/src/assets/icons_old/leave-account.svg +4 -0
  222. package/src/assets/icons_old/link.svg +4 -0
  223. package/src/assets/icons_old/lock-closed.svg +4 -0
  224. package/src/assets/icons_old/lock.svg +4 -0
  225. package/src/assets/icons_old/locked-user.svg +4 -0
  226. package/src/assets/icons_old/marketplace.svg +4 -0
  227. package/src/assets/icons_old/minus.svg +4 -0
  228. package/src/assets/icons_old/monitoring.svg +4 -0
  229. package/src/assets/icons_old/no-logging.svg +4 -0
  230. package/src/assets/icons_old/node-cluster.svg +4 -0
  231. package/src/assets/icons_old/node.svg +4 -0
  232. package/src/assets/icons_old/operations.svg +13 -0
  233. package/src/assets/icons_old/options.svg +4 -0
  234. package/src/assets/icons_old/play.svg +4 -0
  235. package/src/assets/icons_old/plug.svg +4 -0
  236. package/src/assets/icons_old/plugin-clone.svg +4 -0
  237. package/src/assets/icons_old/plugin.svg +4 -0
  238. package/src/assets/icons_old/plugins.svg +4 -0
  239. package/src/assets/icons_old/pod.svg +4 -0
  240. package/src/assets/icons_old/print.svg +4 -0
  241. package/src/assets/icons_old/projects.svg +11 -0
  242. package/src/assets/icons_old/python.svg +4 -0
  243. package/src/assets/icons_old/quorum.svg +4 -0
  244. package/src/assets/icons_old/refresh.svg +4 -0
  245. package/src/assets/icons_old/regenerate.svg +4 -0
  246. package/src/assets/icons_old/region.svg +4 -0
  247. package/src/assets/icons_old/reports.svg +3 -0
  248. package/src/assets/icons_old/request-approve.svg +4 -0
  249. package/src/assets/icons_old/request-decline.svg +4 -0
  250. package/src/assets/icons_old/reseller.svg +4 -0
  251. package/src/assets/icons_old/script.svg +7 -0
  252. package/src/assets/icons_old/search.svg +4 -0
  253. package/src/assets/icons_old/service-account.svg +4 -0
  254. package/src/assets/icons_old/settings.svg +4 -0
  255. package/src/assets/icons_old/sidebar-closed.svg +8 -0
  256. package/src/assets/icons_old/sidebar-open.svg +8 -0
  257. package/src/assets/icons_old/sign-out.svg +4 -0
  258. package/src/assets/icons_old/sign.svg +4 -0
  259. package/src/assets/icons_old/software.svg +4 -0
  260. package/src/assets/icons_old/sql-aggregate.svg +7 -0
  261. package/src/assets/icons_old/sql.svg +7 -0
  262. package/src/assets/icons_old/stack.svg +4 -0
  263. package/src/assets/icons_old/star-empty.svg +4 -0
  264. package/src/assets/icons_old/star-fill.svg +4 -0
  265. package/src/assets/icons_old/subscription.svg +5 -0
  266. package/src/assets/icons_old/support.svg +11 -0
  267. package/src/assets/icons_old/switcher.svg +4 -0
  268. package/src/assets/icons_old/sysadmin.svg +4 -0
  269. package/src/assets/icons_old/tag.svg +4 -0
  270. package/src/assets/icons_old/target.svg +4 -0
  271. package/src/assets/icons_old/tasks.svg +4 -0
  272. package/src/assets/icons_old/tfa-user.svg +4 -0
  273. package/src/assets/icons_old/tfa.svg +4 -0
  274. package/src/assets/icons_old/tokenization.svg +4 -0
  275. package/src/assets/icons_old/tools.svg +4 -0
  276. package/src/assets/icons_old/transition-from.svg +4 -0
  277. package/src/assets/icons_old/transition-to.svg +4 -0
  278. package/src/assets/icons_old/upload.svg +4 -0
  279. package/src/assets/icons_old/user-remove.svg +3 -0
  280. package/src/assets/icons_old/user.svg +4 -0
  281. package/src/assets/icons_old/view-type-cards.svg +4 -0
  282. package/src/assets/icons_old/view-type-list.svg +4 -0
  283. package/src/assets/icons_old/view-type-table.svg +4 -0
  284. package/src/assets/icons_old/warning.svg +4 -0
  285. package/src/assets/icons_old/workflow.svg +3 -0
  286. package/src/assets/icons_old/wrap.svg +4 -0
  287. package/src/assets/icons_old/wrench.svg +4 -0
  288. package/src/assets/images/fortanix_logo_icon.svg +20 -0
  289. package/src/components/actions/Button/Button.module.scss +81 -0
  290. package/src/components/actions/Button/Button.stories.tsx +262 -0
  291. package/src/components/actions/Button/Button.tsx +133 -0
  292. package/src/components/actions/ButtonAsLink/ButtonAsLink.module.scss +13 -0
  293. package/src/components/actions/ButtonAsLink/ButtonAsLink.stories.tsx +49 -0
  294. package/src/components/actions/ButtonAsLink/ButtonAsLink.tsx +56 -0
  295. package/src/components/actions/Link/Link.module.scss +38 -0
  296. package/src/components/actions/Link/Link.stories.tsx +54 -0
  297. package/src/components/actions/Link/Link.tsx +59 -0
  298. package/src/components/actions/LinkAsButton/LinkAsButton.stories.tsx +70 -0
  299. package/src/components/actions/LinkAsButton/LinkAsButton.tsx +59 -0
  300. package/src/components/containers/Alert/Alert.module.scss +41 -0
  301. package/src/components/containers/Alert/Alert.stories.tsx +47 -0
  302. package/src/components/containers/Alert/Alert.tsx +65 -0
  303. package/src/components/containers/Banner/Banner.module.scss +100 -0
  304. package/src/components/containers/Banner/Banner.stories.tsx +198 -0
  305. package/src/components/containers/Banner/Banner.tsx +121 -0
  306. package/src/components/containers/Card/Card.module.scss +32 -0
  307. package/src/components/containers/Card/Card.stories.tsx +67 -0
  308. package/src/components/containers/Card/Card.tsx +48 -0
  309. package/src/components/containers/Dialog/Dialog.module.scss +166 -0
  310. package/src/components/containers/Dialog/Dialog.stories.tsx +32 -0
  311. package/src/components/containers/Dialog/Dialog.tsx +130 -0
  312. package/src/components/containers/Panel/Panel.module.scss +32 -0
  313. package/src/components/containers/Panel/Panel.stories.tsx +46 -0
  314. package/src/components/containers/Panel/Panel.tsx +48 -0
  315. package/src/components/forms/context/Form/Form.module.scss +11 -0
  316. package/src/components/forms/context/Form/Form.stories.tsx +99 -0
  317. package/src/components/forms/context/Form/Form.tsx +106 -0
  318. package/src/components/forms/context/Form/FormOptics.tsx +109 -0
  319. package/src/components/forms/context/SubmitButton/SubmitButton.module.scss +9 -0
  320. package/src/components/forms/context/SubmitButton/SubmitButton.stories.tsx +132 -0
  321. package/src/components/forms/context/SubmitButton/SubmitButton.tsx +98 -0
  322. package/src/components/forms/controls/Checkbox/Checkbox.module.scss +67 -0
  323. package/src/components/forms/controls/Checkbox/Checkbox.stories.tsx +119 -0
  324. package/src/components/forms/controls/Checkbox/Checkbox.tsx +53 -0
  325. package/src/components/forms/controls/Input/Input.module.scss +40 -0
  326. package/src/components/forms/controls/Input/Input.stories.tsx +55 -0
  327. package/src/components/forms/controls/Input/Input.tsx +44 -0
  328. package/src/components/forms/controls/SegmentedControl/SegmentedControl.module.scss +76 -0
  329. package/src/components/forms/controls/SegmentedControl/SegmentedControl.stories.tsx +92 -0
  330. package/src/components/forms/controls/SegmentedControl/SegmentedControl.tsx +103 -0
  331. package/src/components/forms/controls/Select/Select.module.scss +105 -0
  332. package/src/components/forms/controls/Select/Select.stories.tsx +43 -0
  333. package/src/components/forms/controls/Select/Select.tsx +166 -0
  334. package/src/components/forms/controls/Switch/Switch.module.scss +63 -0
  335. package/src/components/forms/controls/Switch/Switch.stories.tsx +50 -0
  336. package/src/components/forms/controls/Switch/Switch.tsx +46 -0
  337. package/src/components/forms/fields/CheckboxField/CheckboxField.module.scss +46 -0
  338. package/src/components/forms/fields/CheckboxField/CheckboxField.stories.tsx +74 -0
  339. package/src/components/forms/fields/CheckboxField/CheckboxField.tsx +118 -0
  340. package/src/components/forms/fields/CheckboxGroup/CheckboxGroup.module.scss +22 -0
  341. package/src/components/forms/fields/CheckboxGroup/CheckboxGroup.stories.tsx +36 -0
  342. package/src/components/forms/fields/CheckboxGroup/CheckboxGroup.tsx +37 -0
  343. package/src/components/forms/fields/InputField/InputField.module.scss +24 -0
  344. package/src/components/forms/fields/InputField/InputField.stories.tsx +57 -0
  345. package/src/components/forms/fields/InputField/InputField.tsx +72 -0
  346. package/src/components/graphics/Icon/Icon.module.scss +42 -0
  347. package/src/components/graphics/Icon/Icon.stories.tsx +67 -0
  348. package/src/components/graphics/Icon/Icon.tsx +50 -0
  349. package/src/components/graphics/PlaceholderEmpty/PlaceholderEmpty.module.scss +76 -0
  350. package/src/components/graphics/PlaceholderEmpty/PlaceholderEmpty.stories.tsx +101 -0
  351. package/src/components/graphics/PlaceholderEmpty/PlaceholderEmpty.tsx +91 -0
  352. package/src/components/graphics/ProgressBar/ProgressBar.module.scss +43 -0
  353. package/src/components/graphics/ProgressBar/ProgressBar.stories.tsx +70 -0
  354. package/src/components/graphics/ProgressBar/ProgressBar.tsx +58 -0
  355. package/src/components/graphics/Spinner/Spinner.module.scss +61 -0
  356. package/src/components/graphics/Spinner/Spinner.stories.tsx +56 -0
  357. package/src/components/graphics/Spinner/Spinner.tsx +41 -0
  358. package/src/components/lists/PropertyList/PropertyList.module.scss +33 -0
  359. package/src/components/lists/PropertyList/PropertyList.stories.tsx +45 -0
  360. package/src/components/lists/PropertyList/PropertyList.tsx +60 -0
  361. package/src/components/navigations/Stepper/Stepper.module.scss +88 -0
  362. package/src/components/navigations/Stepper/Stepper.stories.tsx +68 -0
  363. package/src/components/navigations/Stepper/Stepper.tsx +95 -0
  364. package/src/components/navigations/Tabs/Tabs.module.scss +71 -0
  365. package/src/components/navigations/Tabs/Tabs.stories.tsx +106 -0
  366. package/src/components/navigations/Tabs/Tabs.tsx +121 -0
  367. package/src/components/overlays/DropdownMenu/DropdownMenu.module.scss +113 -0
  368. package/src/components/overlays/DropdownMenu/DropdownMenu.stories.tsx +91 -0
  369. package/src/components/overlays/DropdownMenu/DropdownMenu.tsx +155 -0
  370. package/src/components/overlays/DropdownMenu/DropdownMenuProvider.module.scss +105 -0
  371. package/src/components/overlays/DropdownMenu/DropdownMenuProvider.stories.tsx +71 -0
  372. package/src/components/overlays/DropdownMenu/DropdownMenuProvider.tsx +168 -0
  373. package/src/components/overlays/Modal/Modal.module.scss +185 -0
  374. package/src/components/overlays/Modal/Modal.stories.tsx +144 -0
  375. package/src/components/overlays/Modal/Modal.tsx +202 -0
  376. package/src/components/overlays/Toast/Toast.module.scss +123 -0
  377. package/src/components/overlays/Toast/Toast.stories.tsx +219 -0
  378. package/src/components/overlays/Toast/Toast.tsx +233 -0
  379. package/src/components/overlays/Toast/ToastyOverride.scss +27 -0
  380. package/src/components/overlays/Tooltip/Tooltip.module.scss +162 -0
  381. package/src/components/overlays/Tooltip/Tooltip.stories.tsx +115 -0
  382. package/src/components/overlays/Tooltip/Tooltip.tsx +75 -0
  383. package/src/components/overlays/Tooltip/TooltipProvider.stories.tsx +169 -0
  384. package/src/components/overlays/Tooltip/TooltipProvider.tsx +164 -0
  385. package/src/components/util/Clipboard/Clipboard.tsx +11 -0
  386. package/src/components/util/Popover/Popover.tsx +219 -0
  387. package/src/docs/Changelog.mdx +7 -0
  388. package/src/docs/Colors.mdx +113 -0
  389. package/src/docs/Colors.module.scss +56 -0
  390. package/src/docs/Iconography.mdx +70 -0
  391. package/src/docs/Iconography.module.scss +37 -0
  392. package/src/docs/Introduction.mdx +26 -0
  393. package/src/docs/Typography.mdx +109 -0
  394. package/src/docs/Typography.module.scss +22 -0
  395. package/src/layouts/AppLayout/AppLayout.module.scss +110 -0
  396. package/src/layouts/AppLayout/AppLayout.stories.tsx +112 -0
  397. package/src/layouts/AppLayout/AppLayout.tsx +31 -0
  398. package/src/layouts/AppLayout/Breadcrumbs/Breadcrumbs.module.scss +47 -0
  399. package/src/layouts/AppLayout/Breadcrumbs/Breadcrumbs.stories.tsx +66 -0
  400. package/src/layouts/AppLayout/Breadcrumbs/Breadcrumbs.tsx +63 -0
  401. package/src/layouts/AppLayout/Header/AccountSelector.module.scss +24 -0
  402. package/src/layouts/AppLayout/Header/AccountSelector.stories.tsx +31 -0
  403. package/src/layouts/AppLayout/Header/AccountSelector.tsx +51 -0
  404. package/src/layouts/AppLayout/Header/Header.module.scss +74 -0
  405. package/src/layouts/AppLayout/Header/Header.stories.tsx +30 -0
  406. package/src/layouts/AppLayout/Header/Header.tsx +31 -0
  407. package/src/layouts/AppLayout/Header/SolutionSelector.module.scss +24 -0
  408. package/src/layouts/AppLayout/Header/SolutionSelector.stories.tsx +31 -0
  409. package/src/layouts/AppLayout/Header/SolutionSelector.tsx +50 -0
  410. package/src/layouts/AppLayout/Header/UserMenu.module.scss +31 -0
  411. package/src/layouts/AppLayout/Header/UserMenu.stories.tsx +32 -0
  412. package/src/layouts/AppLayout/Header/UserMenu.tsx +67 -0
  413. package/src/layouts/AppLayout/Logo/Logo.module.scss +78 -0
  414. package/src/layouts/AppLayout/Logo/Logo.tsx +38 -0
  415. package/src/layouts/AppLayout/Nav/Nav.module.scss +73 -0
  416. package/src/layouts/AppLayout/Nav/Nav.stories.tsx +32 -0
  417. package/src/layouts/AppLayout/Nav/Nav.tsx +75 -0
  418. package/src/layouts/AppLayout/Sidebar/Sidebar.module.scss +46 -0
  419. package/src/layouts/AppLayout/Sidebar/Sidebar.stories.tsx +30 -0
  420. package/src/layouts/AppLayout/Sidebar/Sidebar.tsx +33 -0
  421. package/src/layouts/FormLayout/FormLayout.module.scss +19 -0
  422. package/src/layouts/FormLayout/FormLayout.stories.tsx +64 -0
  423. package/src/layouts/FormLayout/FormLayout.tsx +32 -0
  424. package/src/styling/accessibility.css +24 -0
  425. package/src/styling/context/theming.scss +26 -0
  426. package/src/styling/context/theming_mixins.scss +79 -0
  427. package/src/styling/defs.scss +60 -0
  428. package/src/styling/fonts.css +126 -0
  429. package/src/styling/fonts_mixins.scss +16 -0
  430. package/src/styling/global.scss +49 -0
  431. package/src/styling/lib/normalize.css +78 -0
  432. package/src/styling/lib/reset-custom.css +58 -0
  433. package/src/styling/lib/reset.css +115 -0
  434. package/src/styling/main.scss +29 -0
  435. package/src/styling/variables.css +18 -0
  436. package/src/styling/variables.scss +928 -0
  437. package/src/styling/variables.ts +64 -0
  438. package/src/types/globals.d.ts +14 -0
  439. package/src/types/vite-env.d.ts +1 -0
  440. package/src/typography/BodyText/BodyText.mixins.scss +224 -0
  441. package/src/typography/BodyText/BodyText.module.scss +28 -0
  442. package/src/typography/BodyText/BodyText.stories.tsx +109 -0
  443. package/src/typography/BodyText/BodyText.tsx +30 -0
  444. package/src/typography/Heading/Heading.mixins.scss +42 -0
  445. package/src/typography/Heading/Heading.module.scss +15 -0
  446. package/src/typography/Heading/Heading.stories.tsx +112 -0
  447. package/src/typography/Heading/Heading.tsx +57 -0
  448. package/src/util/componentUtil.ts +19 -0
  449. package/src/util/drag.ts +197 -0
  450. package/src/util/reactUtil.ts +40 -0
  451. package/src/util/storybook/OverflowTester.css +13 -0
  452. package/src/util/storybook/OverflowTester.tsx +30 -0
  453. package/src/util/time.ts +12 -0
  454. package/src/util/types.ts +8 -0
@@ -0,0 +1,168 @@
1
+ /* Copyright (c) Fortanix, Inc.
2
+ |* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
3
+ |* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+ import { mergeRefs } from '../../../util/reactUtil.ts';
6
+ import { classNames as cx, type ComponentProps } from '../../../util/componentUtil.ts';
7
+ import * as React from 'react';
8
+
9
+ import { useListNavigation, type Placement } from '@floating-ui/react';
10
+ import { usePopover } from '../../util/Popover/Popover.tsx';
11
+
12
+ import { DropdownMenuContext, type OptionKey, type OptionDef, Action, Option, DropdownMenu } from './DropdownMenu.tsx';
13
+
14
+ import cl from './DropdownMenuProvider.module.scss';
15
+
16
+
17
+ export { cl as DropdownMenuClassNames };
18
+
19
+
20
+ export type AnchorRenderArgs = {
21
+ props: (userProps?: undefined | React.HTMLProps<Element>) => Record<string, unknown>,
22
+ state: DropdownMenuContext,
23
+ };
24
+ export type DropdownMenuProviderProps = Omit<ComponentProps<typeof DropdownMenu>, 'children'> & {
25
+ /**
26
+ * The content to render, which should contain the anchor. This should be a render prop which takes props to
27
+ * apply on the anchor element. Alternatively, a single element can be provided to which the props are applied.
28
+ */
29
+ children?: ((args: AnchorRenderArgs) => React.ReactNode) | React.ReactNode,
30
+
31
+ /** Whether this component should be unstyled. */
32
+ unstyled?: undefined | boolean,
33
+
34
+ /** The dropdown items. */
35
+ items: React.ReactNode,
36
+
37
+ /** Override the default placement */
38
+ placement?: undefined | Placement,
39
+
40
+ /** Enable more precise tracking of the anchor, at the cost of performance. */
41
+ enablePreciseTracking?: undefined | boolean,
42
+ };
43
+ /**
44
+ * Provider for a dropdown menu overlay with its trigger.
45
+ */
46
+ export const DropdownMenuProvider = Object.assign(
47
+ (props: DropdownMenuProviderProps) => {
48
+ const { children, unstyled = false, items, placement = 'bottom', enablePreciseTracking, ...propsRest } = props;
49
+
50
+ const selectedRef = React.useRef<React.ElementRef<typeof Option>>(null);
51
+ const [selected, setSelected] = React.useState<null | OptionDef>(null);
52
+
53
+ const listRef = React.useRef([]);
54
+ const [activeIndex, setActiveIndex] = React.useState<null | number>(null);
55
+ const {
56
+ refs,
57
+ placement: placementEffective,
58
+ floatingStyles,
59
+ getReferenceProps,
60
+ getFloatingProps,
61
+ getItemProps,
62
+ setIsOpen,
63
+ } = usePopover({
64
+ placement: placement,
65
+ offset: 8,
66
+ floatingUiFlipOptions: {
67
+ fallbackAxisSideDirection: 'none',
68
+ fallbackStrategy: 'initialPlacement',
69
+ },
70
+ floatingUiInteractions: context => [
71
+ useListNavigation(context, {
72
+ listRef,
73
+ activeIndex,
74
+ onNavigate: setActiveIndex,
75
+ }),
76
+ ],
77
+ });
78
+
79
+ const context: DropdownMenuContext = React.useMemo((): DropdownMenuContext => ({
80
+ optionProps: () => getItemProps(),
81
+ selectedOption: selected?.optionKey ?? null,
82
+ selectOption: (option: OptionDef) => {
83
+ setSelected(option);
84
+ setIsOpen(false);
85
+ selectedRef.current?.focus(); // Return focus
86
+ },
87
+ close: () => { setIsOpen(false); },
88
+ }), [selected, setIsOpen, getItemProps]);
89
+
90
+ const renderAnchor = () => {
91
+ const anchorProps: AnchorRenderArgs['props'] = (userProps?: undefined | React.HTMLProps<Element>) => {
92
+ const userPropsRef: undefined | string | React.Ref<Element> = userProps?.ref ?? undefined;
93
+ if (typeof userPropsRef === 'string') {
94
+ // We can't merge refs if one of the refs is a string
95
+ console.error(`Failed to render DropdownMenuProvider, due to use of legacy string ref`);
96
+ return (userProps ?? {}) as Record<string, unknown>;
97
+ }
98
+
99
+ return {
100
+ ...getReferenceProps(userProps),
101
+ ref: userPropsRef ? mergeRefs(userPropsRef, refs.setReference) : refs.setReference,
102
+ };
103
+ };
104
+
105
+ if (typeof children === 'function') {
106
+ return children({ props: anchorProps, state: context });
107
+ }
108
+
109
+ // If a render prop is not used, try to attach it to the element directly.
110
+ // NOTE: `cloneElement` is marked as a legacy function by React. Recommended is to use a render prop instead.
111
+ if (!React.isValidElement(children)) {
112
+ return <span {...anchorProps()}>{children}</span>;
113
+ }
114
+ if (React.Children.count(children) === 1) {
115
+ return React.cloneElement(children, anchorProps(children.props as React.HTMLProps<Element>));
116
+ }
117
+
118
+ console.error(`Invalid children passed to DropdownMenuProvider, expected a render prop or single child element.`);
119
+ return children;
120
+ };
121
+
122
+ return (
123
+ // @ts-ignore React 19
124
+ <DropdownMenuContext value={context}>
125
+ {renderAnchor()}
126
+
127
+ <DropdownMenu
128
+ {...getFloatingProps({
129
+ popover: 'manual',
130
+ style: floatingStyles,
131
+ ...propsRest,
132
+ className: cx(propsRest.className),
133
+ })}
134
+ tabIndex={undefined}
135
+ ref={mergeRefs<HTMLUListElement>(refs.setFloating, propsRest.ref)}
136
+ data-placement={placementEffective}
137
+ >
138
+ {items}
139
+ </DropdownMenu>
140
+ {/* <Button variant="primary"
141
+ {...propsRest}
142
+ className={cx(
143
+ 'bk',
144
+ { [cl['bk-dropdown']]: !unstyled },
145
+ propsRest.className,
146
+ )}
147
+ {...getReferenceProps()}
148
+ ref={mergeRefs(selectedRef, refs.setReference as any)}
149
+ >
150
+ {context.selectedOption ? `Selected: ${context.selectedOption}` : 'Open dropdown'}
151
+ </Button> */}
152
+ {/* <ul
153
+ ref={refs.setFloating}
154
+ data-placement={placement}
155
+ {...getFloatingProps({
156
+ popover: 'manual',
157
+ style: floatingStyles,
158
+ className: cl['bk-dropdown__dropdown'],
159
+ })}
160
+ tabIndex={undefined} // Overwrite `tabIndex={-1}` so that we don't allow programmatic focus
161
+ >
162
+ {children}
163
+ </ul> */}
164
+ </DropdownMenuContext>
165
+ );
166
+ },
167
+ { Action, Option },
168
+ );
@@ -0,0 +1,185 @@
1
+ /* Copyright (c) Fortanix, Inc.
2
+ |* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
3
+ |* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+ @use '../../../styling/defs.scss' as bk;
6
+ @use '../../containers/Panel/Panel.module.scss' as Panel;
7
+
8
+ @layer baklava.components {
9
+ .bk-modal {
10
+ @include bk.component-base(bk-modal);
11
+
12
+ @include Panel.bk-panel;
13
+
14
+ /* --bk-modal-background-color: color-mix(in srgb, var(--bk-panel-background-color) 80%, transparent); */
15
+ --bk-modal-background-color: var(--bk-panel-background-color);
16
+
17
+ margin: auto;
18
+ padding: 0;
19
+ height: fit-content;
20
+ min-height: bk.$spacing-16;
21
+ max-width: calc(100% - bk.$spacing-6);
22
+ max-height: calc(100% - bk.$spacing-6);
23
+
24
+ box-shadow: 0 8px 10px 1px rgba(0 0 0 / 14%), 0 3px 14px 2px rgba(0 0 0 / 12%), 0 5px 5px -3px rgba(0 0 0 / 3%);
25
+ background-color: var(--bk-modal-background-color);
26
+ border-radius: bk.$sizing-2;
27
+
28
+ display: none; /* flex */
29
+ flex-direction: column;
30
+
31
+ &.bk-modal-small {
32
+ // 484px
33
+ width: calc(484 * bk.$size-1);
34
+ }
35
+ &.bk-modal-medium {
36
+ // 684px
37
+ width: calc(684 * bk.$size-1);
38
+ }
39
+ &.bk-modal-large {
40
+ // 784px
41
+ width: calc(784 * bk.$size-1);
42
+ }
43
+ &.bk-modal-x-large {
44
+ // 906px
45
+ width: calc(906 * bk.$size-1);
46
+ }
47
+ &.bk-modal-fullscreen {
48
+ width: calc(100% - bk.$spacing-3);
49
+ height: calc(100% - bk.$spacing-3);
50
+ }
51
+ .bk-modal__header {
52
+ position: sticky;
53
+ top: 0;
54
+ padding: 0;
55
+
56
+ background: var(--bk-modal-background-color);
57
+
58
+ display: flex;
59
+ flex-direction: row;
60
+ align-items: baseline;
61
+ margin-bottom: bk.$spacing-7;
62
+
63
+ h1 {
64
+ font-size: 16px; // do not match bk variable sizes
65
+ font-weight: bk.$font-weight-semibold;
66
+ }
67
+
68
+ :nth-child(1 of :global(.action)) {
69
+ margin-left: auto;
70
+ }
71
+ }
72
+ .bk-modal__close {
73
+ position: absolute;
74
+ right: bk.$spacing-8;
75
+ top: bk.$spacing-8;
76
+ z-index: 1;
77
+ }
78
+ .bk-modal__container {
79
+ padding: bk.$spacing-8;
80
+ padding-bottom: bk.$spacing-9;
81
+ flex-direction: column;
82
+ overflow: hidden;
83
+ display: flex;
84
+ flex: 1;
85
+ }
86
+ .bk-modal__content {
87
+ flex: 1; /* Make sure we cover all available space */
88
+ overflow: auto;
89
+ }
90
+
91
+ transition:
92
+ opacity 1ms ease-out,
93
+ scale 1ms ease-out,
94
+ overlay 1ms ease-out allow-discrete,
95
+ display 1ms ease-out allow-discrete;
96
+ opacity: 0;
97
+ scale: 0.98 0.98;
98
+ transition-duration: 200ms; /* Exit transition duration */
99
+
100
+ /* Variant: slide out */
101
+ --modal-slide-out-inset: var(--bk-sizing-3);
102
+ &:is(.bk-modal--slide-out-left, .bk-modal--slide-out-right) {
103
+ position: fixed;
104
+ inset: 0;
105
+ margin: 0;
106
+ width: 60vw;
107
+ height: auto;
108
+ max-height: 100%;
109
+
110
+ &.bk-modal--slide-out-left {
111
+ right: auto;
112
+ transform-origin: center left;
113
+ border-top-left-radius: 0;
114
+ border-bottom-left-radius: 0;
115
+ }
116
+ &.bk-modal--slide-out-right {
117
+ left: auto;
118
+ transform-origin: center right;
119
+ border-top-right-radius: 0;
120
+ border-bottom-right-radius: 0;
121
+ }
122
+
123
+ opacity: 1;
124
+ transform: scaleX(0);
125
+ &:modal {
126
+ transform: scaleX(1);
127
+
128
+ @starting-style {
129
+ opacity: 1;
130
+ transform: scaleX(0);
131
+ }
132
+ }
133
+
134
+ .bk-modal__content {
135
+ overflow: auto;
136
+ }
137
+ }
138
+
139
+ /* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#animating_dialogs */
140
+
141
+ &:modal {
142
+ display: flex;
143
+ opacity: 1;
144
+ scale: 1 1;
145
+ transition-duration: 120ms; /* Enter transition duration */
146
+ transition-timing-function: ease-in;
147
+
148
+ @starting-style {
149
+ opacity: 0;
150
+ scale: 1.05 1.05;
151
+ }
152
+ }
153
+ }
154
+
155
+ /* Note: `::backdrop` cannot be nested/scoped (at least in Chrome v120) */
156
+ .bk-modal::backdrop {
157
+ --transition-time: 200ms;
158
+ background-color: rgb(0 0 0 / 0%);
159
+ transition:
160
+ display var(--transition-time) allow-discrete,
161
+ overlay var(--transition-time) allow-discrete,
162
+ background-color var(--transition-time);
163
+ }
164
+ .bk-modal:modal::backdrop,
165
+ .bk-modal-spinner::backdrop {
166
+ background-color: rgb(0 0 0 / 20%);
167
+ backdrop-filter: blur(5px); /* Should be in px, not rem (blur effect should be constant) */
168
+ }
169
+ @starting-style {
170
+ .bk-modal:modal::backdrop {
171
+ background-color: rgb(0 0 0 / 0%);
172
+ }
173
+ }
174
+
175
+ .bk-modal-spinner {
176
+ outline: none !important; // prevent blue border on Esc pressing
177
+
178
+ .bk-modal__content {
179
+ display: flex;
180
+ justify-content: center;
181
+ align-items: center;
182
+ overflow: hidden;
183
+ }
184
+ }
185
+ }
@@ -0,0 +1,144 @@
1
+ /* Copyright (c) Fortanix, Inc.
2
+ |* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
3
+ |* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+ import * as React from 'react';
6
+
7
+ import type { Meta, StoryObj } from '@storybook/react';
8
+
9
+ import { ModalClassNames as cl } from './Modal.tsx';
10
+ import { OverflowTester } from '../../../util/storybook/OverflowTester.tsx';
11
+ import { Modal } from './Modal.tsx';
12
+ import { Button } from '../../actions/Button/Button.tsx';
13
+ import { Spinner } from '../../graphics/Spinner/Spinner.tsx';
14
+
15
+
16
+ type ButtonArgs = React.ComponentProps<typeof Modal>;
17
+ type Story = StoryObj<ButtonArgs>;
18
+
19
+ export default {
20
+ component: Modal,
21
+ parameters: {
22
+ layout: 'centered',
23
+ },
24
+ tags: ['autodocs'],
25
+ argTypes: {
26
+ },
27
+ } satisfies Meta<ButtonArgs>;
28
+
29
+
30
+ type ModalWithTriggerProps = Omit<React.ComponentProps<typeof Modal>, 'active' | 'onClose'> & {
31
+ triggerLabel?: string,
32
+ };
33
+ const ModalWithTrigger = ({ triggerLabel = 'Open modal', ...modalProps }: ModalWithTriggerProps) => {
34
+ const [active, setActive] = React.useState(false);
35
+ const onClose = React.useCallback(() => { setActive(false); }, []);
36
+ return (
37
+ <>
38
+ <Button variant="primary" onPress={() => { setActive(true); }}>{triggerLabel}</Button>
39
+ <Modal {...modalProps} active={active} onClose={onClose}/>
40
+ </>
41
+ );
42
+ };
43
+
44
+ const reusableModalChildren: React.JSX.Element = (
45
+ <>
46
+ <Modal.Header>
47
+ <h1>Modal title</h1>
48
+ </Modal.Header>
49
+ <Modal.Content>
50
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do iusmod tempor incididunt ut labore et dolore magna aliqua.</p>
51
+
52
+ <ModalWithTrigger triggerLabel="Open Submodal">
53
+ <Modal.Header>
54
+ <h1>Submodal title</h1>
55
+ </Modal.Header>
56
+ <Modal.Content>
57
+ <p>This is a submodal</p>
58
+ <OverflowTester/>
59
+ </Modal.Content>
60
+ </ModalWithTrigger>
61
+
62
+ <OverflowTester/>
63
+ </Modal.Content>
64
+ <Modal.Footer>This is a modal footer with eventual action buttons</Modal.Footer>
65
+ </>
66
+ );
67
+
68
+ export const ModalSizeSmall: Story = {
69
+ render: () => (
70
+ <ModalWithTrigger size="small">
71
+ {reusableModalChildren}
72
+ </ModalWithTrigger>
73
+ ),
74
+ };
75
+
76
+ export const ModalSizeMedium: Story = {
77
+ render: () => (
78
+ <ModalWithTrigger size="medium">
79
+ {reusableModalChildren}
80
+ </ModalWithTrigger>
81
+ ),
82
+ };
83
+
84
+ export const ModalSizeLarge: Story = {
85
+ render: () => (
86
+ <ModalWithTrigger size="large">
87
+ {reusableModalChildren}
88
+ </ModalWithTrigger>
89
+ ),
90
+ };
91
+
92
+ export const ModalSizeXLarge: Story = {
93
+ render: () => (
94
+ <ModalWithTrigger size="x-large">
95
+ {reusableModalChildren}
96
+ </ModalWithTrigger>
97
+ ),
98
+ };
99
+
100
+ export const ModalSizeFullScreen: Story = {
101
+ render: () => (
102
+ <ModalWithTrigger size="fullscreen">
103
+ {reusableModalChildren}
104
+ </ModalWithTrigger>
105
+ ),
106
+ };
107
+
108
+ export const ModalUncloseable: Story = {
109
+ render: () => (
110
+ <ModalWithTrigger closeable={false}>
111
+ {reusableModalChildren}
112
+ </ModalWithTrigger>
113
+ ),
114
+ };
115
+
116
+ type ModalWithSpinnerTriggerProps = Omit<React.ComponentProps<typeof Modal>, 'active' | 'onClose'> & {
117
+ triggerLabel?: string,
118
+ };
119
+ const ModalWithSpinnerTrigger = ({ triggerLabel = 'Open modal with spinner (it will close in 5 seconds)', ...modalProps }: ModalWithSpinnerTriggerProps) => {
120
+ const [active, setActive] = React.useState(false);
121
+ const onPress = () => {
122
+ setActive(true);
123
+ setTimeout(() => {
124
+ setActive(false);
125
+ }, 5000);
126
+ }
127
+ const onClose = React.useCallback(() => { setActive(false); }, []);
128
+ return (
129
+ <>
130
+ <Button variant="primary" onPress={onPress}>{triggerLabel}</Button>
131
+ <Modal {...modalProps} active={active} onClose={onClose} closeable={false} className={cl['bk-modal-spinner']} size="fullscreen"/>
132
+ </>
133
+ );
134
+ };
135
+
136
+ export const ModalWithSpinner: Story = {
137
+ render: () => (
138
+ <ModalWithSpinnerTrigger unstyled={true}>
139
+ <Modal.Content>
140
+ <Spinner size="large" />
141
+ </Modal.Content>
142
+ </ModalWithSpinnerTrigger>
143
+ ),
144
+ };
@@ -0,0 +1,202 @@
1
+ /* Copyright (c) Fortanix, Inc.
2
+ |* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
3
+ |* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+ import { type ClassNameArgument, classNames as cx } from '../../../util/componentUtil.ts';
6
+ import * as React from 'react';
7
+
8
+ import { Icon } from '../../graphics/Icon/Icon.tsx';
9
+
10
+ import cl from './Modal.module.scss';
11
+
12
+ export { cl as ModalClassNames };
13
+
14
+
15
+ type ModalHeaderProps = React.PropsWithChildren<{
16
+ unstyled?: boolean;
17
+ className?: ClassNameArgument;
18
+ }>;
19
+
20
+ /* Modal Header component */
21
+ const ModalHeader = ({ children, unstyled, className }: ModalHeaderProps) => (
22
+ <header
23
+ className={cx(
24
+ {
25
+ bk: true,
26
+ [cl['bk-modal__header'] as string]: !unstyled,
27
+ },
28
+ className,
29
+ )}
30
+ >
31
+ {children}
32
+ </header>
33
+ );
34
+
35
+ type ModalContentProps = React.PropsWithChildren<{
36
+ unstyled?: boolean;
37
+ className?: ClassNameArgument;
38
+ }>;
39
+
40
+ /* Modal Content component */
41
+ const ModalContent = ({ children, unstyled, className }: ModalContentProps) => (
42
+ <section
43
+ className={cx(
44
+ {
45
+ bk: true,
46
+ 'body-text': true,
47
+ [cl['bk-modal__content'] as string]: !unstyled,
48
+ },
49
+ className,
50
+ )}
51
+ >
52
+ {children}
53
+ </section>
54
+ );
55
+
56
+ type ModalFooterProps = React.PropsWithChildren<{
57
+ unstyled?: boolean;
58
+ className?: ClassNameArgument;
59
+ }>;
60
+
61
+ /* Modal Footer component */
62
+ const ModalFooter = ({ children, unstyled, className }: ModalFooterProps) => (
63
+ <footer
64
+ className={cx(
65
+ {
66
+ bk: true,
67
+ [cl['bk-modal__footer'] as string]: !unstyled,
68
+ },
69
+ className,
70
+ )}
71
+ >
72
+ {children}
73
+ </footer>
74
+ );
75
+
76
+ type ModalProps = React.PropsWithChildren<{
77
+ unstyled?: boolean;
78
+ size?: 'small' | 'medium' | 'large' | 'x-large' | 'fullscreen';
79
+ active: boolean;
80
+ className?: ClassNameArgument;
81
+ onClose: () => void;
82
+ closeable?: boolean;
83
+ }>;
84
+
85
+ /**
86
+ * Modal component.
87
+ */
88
+ const Modal = ({
89
+ children,
90
+ unstyled,
91
+ className,
92
+ size = 'medium',
93
+ closeable = true,
94
+ active,
95
+ onClose,
96
+ }: ModalProps) => {
97
+ const dialogRef = React.useRef<HTMLDialogElement>(null);
98
+
99
+ // Sync the `active` flag with the DOM dialog
100
+ React.useEffect(() => {
101
+ const dialog = dialogRef.current;
102
+ if (dialog === null) {
103
+ return;
104
+ }
105
+
106
+ if (active && !dialog.open) {
107
+ dialog.showModal();
108
+ } else if (!active && dialog.open) {
109
+ dialog.close();
110
+ }
111
+ }, [active]);
112
+
113
+ // Sync the dialog close event with the `active` flag
114
+ const handleCloseEvent = React.useCallback(
115
+ (event: Event): void => {
116
+ const dialog = dialogRef.current;
117
+ if (dialog === null) {
118
+ return;
119
+ }
120
+
121
+ if (active && event.target === dialog) {
122
+ onClose();
123
+ }
124
+ },
125
+ [active, onClose],
126
+ );
127
+ React.useEffect(() => {
128
+ const dialog = dialogRef.current;
129
+ if (dialog === null) {
130
+ return;
131
+ }
132
+
133
+ dialog.addEventListener('close', handleCloseEvent);
134
+ return () => {
135
+ dialog.removeEventListener('close', handleCloseEvent);
136
+ };
137
+ }, [handleCloseEvent]);
138
+
139
+ const close = React.useCallback(() => {
140
+ onClose();
141
+ }, [onClose]);
142
+
143
+ const handleDialogClick = React.useCallback(
144
+ (event: React.MouseEvent) => {
145
+ const dialog = dialogRef.current;
146
+ if (dialog !== null && event.target === dialog && closeable) {
147
+ // Note: clicking the backdrop just results in an event where the target is the `<dialog>` element. In order to
148
+ // distinguish between the backdrop and the modal content, we assume that the `<dialog>` is fully covered by
149
+ // another element. In our case, `bk-modal__content` must cover the whole `<dialog>` otherwise this will not work.
150
+ close();
151
+ }
152
+ },
153
+ [close, closeable],
154
+ );
155
+
156
+ // "onKeyDown" instead of "onCancel" as the latter is only fired after the cancel already initiated
157
+ const handleDialogKeyDown = (event: React.KeyboardEvent) => {
158
+ if (event.key === 'Escape' && !closeable) {
159
+ event.preventDefault();
160
+ }
161
+ };
162
+
163
+ return (
164
+ // biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
165
+ <dialog
166
+ ref={dialogRef}
167
+ className={cx(
168
+ {
169
+ bk: true,
170
+ [cl['bk-modal-small'] as string]: size === 'small',
171
+ [cl['bk-modal-medium'] as string]: size === 'medium',
172
+ [cl['bk-modal-large'] as string]: size === 'large',
173
+ [cl['bk-modal-x-large'] as string]: size === 'x-large',
174
+ [cl['bk-modal-fullscreen'] as string]: size === 'fullscreen',
175
+ [cl['bk-modal'] as string]: !unstyled,
176
+ },
177
+ className,
178
+ )}
179
+ onClick={handleDialogClick}
180
+ onKeyDown={handleDialogKeyDown}
181
+ >
182
+ {closeable && (
183
+ <button
184
+ type="button"
185
+ className={cx(cl['bk-modal__close'])}
186
+ onClick={close}
187
+ >
188
+ <Icon icon="cross" />
189
+ </button>
190
+ )}
191
+ <div className={cx(cl['bk-modal__container'])}>
192
+ {children}
193
+ </div>
194
+ </dialog>
195
+ );
196
+ };
197
+
198
+ Modal.Content = ModalContent;
199
+ Modal.Header = ModalHeader;
200
+ Modal.Footer = ModalFooter;
201
+
202
+ export { Modal };