tempest-react-sdk 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AIChat/AIChatTurn.cjs +1 -1
- package/dist/components/AIChat/AIChatTurn.js +4 -4
- package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
- package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.js +11 -11
- package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
- package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.cjs +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.js +21 -21
- package/dist/components/Sidebar/Sidebar.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.js +91 -38
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.module.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.module.js +12 -8
- package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
- package/dist/forms/masked-inputs.cjs +1 -1
- package/dist/forms/masked-inputs.js +12 -12
- package/dist/http/api-client.cjs +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js +45 -31
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/describe-api-error.cjs +1 -1
- package/dist/http/describe-api-error.cjs.map +1 -1
- package/dist/http/describe-api-error.js +11 -7
- package/dist/http/describe-api-error.js.map +1 -1
- package/dist/http/errors.cjs +1 -1
- package/dist/http/errors.cjs.map +1 -1
- package/dist/http/errors.js +38 -21
- package/dist/http/errors.js.map +1 -1
- package/dist/http/use-describe-api-error.cjs +1 -1
- package/dist/http/use-describe-api-error.cjs.map +1 -1
- package/dist/http/use-describe-api-error.js +14 -10
- package/dist/http/use-describe-api-error.js.map +1 -1
- package/dist/icons/Icon.cjs +1 -1
- package/dist/icons/Icon.cjs.map +1 -1
- package/dist/icons/Icon.js +15 -14
- package/dist/icons/Icon.js.map +1 -1
- package/dist/icons/IconPicker.cjs +2 -0
- package/dist/icons/IconPicker.cjs.map +1 -0
- package/dist/icons/IconPicker.js +49 -0
- package/dist/icons/IconPicker.js.map +1 -0
- package/dist/icons/IconPicker.module.cjs +2 -0
- package/dist/icons/IconPicker.module.cjs.map +1 -0
- package/dist/icons/IconPicker.module.js +10 -0
- package/dist/icons/IconPicker.module.js.map +1 -0
- package/dist/icons/alias.cjs +2 -0
- package/dist/icons/alias.cjs.map +1 -0
- package/dist/icons/alias.js +9 -0
- package/dist/icons/alias.js.map +1 -0
- package/dist/icons/generated/loaders.cjs +1 -1
- package/dist/icons/generated/loaders.cjs.map +1 -1
- package/dist/icons/generated/loaders.js +273 -28
- package/dist/icons/generated/loaders.js.map +1 -1
- package/dist/icons/generated/shard-00.cjs +2 -0
- package/dist/icons/generated/shard-00.cjs.map +1 -0
- package/dist/icons/generated/shard-00.js +48 -0
- package/dist/icons/generated/shard-00.js.map +1 -0
- package/dist/icons/generated/shard-01.cjs +2 -0
- package/dist/icons/generated/shard-01.cjs.map +1 -0
- package/dist/icons/generated/shard-01.js +48 -0
- package/dist/icons/generated/shard-01.js.map +1 -0
- package/dist/icons/generated/shard-02.cjs +2 -0
- package/dist/icons/generated/shard-02.cjs.map +1 -0
- package/dist/icons/generated/shard-02.js +48 -0
- package/dist/icons/generated/shard-02.js.map +1 -0
- package/dist/icons/generated/shard-03.cjs +2 -0
- package/dist/icons/generated/shard-03.cjs.map +1 -0
- package/dist/icons/generated/shard-03.js +48 -0
- package/dist/icons/generated/shard-03.js.map +1 -0
- package/dist/icons/generated/shard-04.cjs +2 -0
- package/dist/icons/generated/shard-04.cjs.map +1 -0
- package/dist/icons/generated/shard-04.js +48 -0
- package/dist/icons/generated/shard-04.js.map +1 -0
- package/dist/icons/generated/shard-05.cjs +2 -0
- package/dist/icons/generated/shard-05.cjs.map +1 -0
- package/dist/icons/generated/shard-05.js +48 -0
- package/dist/icons/generated/shard-05.js.map +1 -0
- package/dist/icons/generated/shard-06.cjs +2 -0
- package/dist/icons/generated/shard-06.cjs.map +1 -0
- package/dist/icons/generated/shard-06.js +48 -0
- package/dist/icons/generated/shard-06.js.map +1 -0
- package/dist/icons/generated/shard-07.cjs +2 -0
- package/dist/icons/generated/shard-07.cjs.map +1 -0
- package/dist/icons/generated/shard-07.js +48 -0
- package/dist/icons/generated/shard-07.js.map +1 -0
- package/dist/icons/generated/shard-08.cjs +2 -0
- package/dist/icons/generated/shard-08.cjs.map +1 -0
- package/dist/icons/generated/shard-08.js +48 -0
- package/dist/icons/generated/shard-08.js.map +1 -0
- package/dist/icons/generated/shard-09.cjs +2 -0
- package/dist/icons/generated/shard-09.cjs.map +1 -0
- package/dist/icons/generated/shard-09.js +48 -0
- package/dist/icons/generated/shard-09.js.map +1 -0
- package/dist/icons/generated/shard-10.cjs +2 -0
- package/dist/icons/generated/shard-10.cjs.map +1 -0
- package/dist/icons/generated/shard-10.js +48 -0
- package/dist/icons/generated/shard-10.js.map +1 -0
- package/dist/icons/generated/shard-11.cjs +2 -0
- package/dist/icons/generated/shard-11.cjs.map +1 -0
- package/dist/icons/generated/shard-11.js +48 -0
- package/dist/icons/generated/shard-11.js.map +1 -0
- package/dist/icons/generated/shard-12.cjs +2 -0
- package/dist/icons/generated/shard-12.cjs.map +1 -0
- package/dist/icons/generated/shard-12.js +48 -0
- package/dist/icons/generated/shard-12.js.map +1 -0
- package/dist/icons/generated/shard-13.cjs +2 -0
- package/dist/icons/generated/shard-13.cjs.map +1 -0
- package/dist/icons/generated/shard-13.js +48 -0
- package/dist/icons/generated/shard-13.js.map +1 -0
- package/dist/icons/generated/shard-14.cjs +2 -0
- package/dist/icons/generated/shard-14.cjs.map +1 -0
- package/dist/icons/generated/shard-14.js +48 -0
- package/dist/icons/generated/shard-14.js.map +1 -0
- package/dist/icons/generated/shard-15.cjs +2 -0
- package/dist/icons/generated/shard-15.cjs.map +1 -0
- package/dist/icons/generated/shard-15.js +48 -0
- package/dist/icons/generated/shard-15.js.map +1 -0
- package/dist/icons/generated/shard-16.cjs +2 -0
- package/dist/icons/generated/shard-16.cjs.map +1 -0
- package/dist/icons/generated/shard-16.js +48 -0
- package/dist/icons/generated/shard-16.js.map +1 -0
- package/dist/icons/generated/shard-17.cjs +2 -0
- package/dist/icons/generated/shard-17.cjs.map +1 -0
- package/dist/icons/generated/shard-17.js +48 -0
- package/dist/icons/generated/shard-17.js.map +1 -0
- package/dist/icons/generated/shard-18.cjs +2 -0
- package/dist/icons/generated/shard-18.cjs.map +1 -0
- package/dist/icons/generated/shard-18.js +48 -0
- package/dist/icons/generated/shard-18.js.map +1 -0
- package/dist/icons/generated/shard-19.cjs +2 -0
- package/dist/icons/generated/shard-19.cjs.map +1 -0
- package/dist/icons/generated/shard-19.js +48 -0
- package/dist/icons/generated/shard-19.js.map +1 -0
- package/dist/icons/generated/shard-20.cjs +2 -0
- package/dist/icons/generated/shard-20.cjs.map +1 -0
- package/dist/icons/generated/shard-20.js +48 -0
- package/dist/icons/generated/shard-20.js.map +1 -0
- package/dist/icons/generated/shard-21.cjs +2 -0
- package/dist/icons/generated/shard-21.cjs.map +1 -0
- package/dist/icons/generated/shard-21.js +48 -0
- package/dist/icons/generated/shard-21.js.map +1 -0
- package/dist/icons/generated/shard-22.cjs +2 -0
- package/dist/icons/generated/shard-22.cjs.map +1 -0
- package/dist/icons/generated/shard-22.js +48 -0
- package/dist/icons/generated/shard-22.js.map +1 -0
- package/dist/icons/generated/shard-23.cjs +2 -0
- package/dist/icons/generated/shard-23.cjs.map +1 -0
- package/dist/icons/generated/shard-23.js +48 -0
- package/dist/icons/generated/shard-23.js.map +1 -0
- package/dist/icons/generated/shard-24.cjs +2 -0
- package/dist/icons/generated/shard-24.cjs.map +1 -0
- package/dist/icons/generated/shard-24.js +48 -0
- package/dist/icons/generated/shard-24.js.map +1 -0
- package/dist/icons/generated/shard-25.cjs +2 -0
- package/dist/icons/generated/shard-25.cjs.map +1 -0
- package/dist/icons/generated/shard-25.js +48 -0
- package/dist/icons/generated/shard-25.js.map +1 -0
- package/dist/icons/generated/shard-26.cjs +2 -0
- package/dist/icons/generated/shard-26.cjs.map +1 -0
- package/dist/icons/generated/shard-26.js +48 -0
- package/dist/icons/generated/shard-26.js.map +1 -0
- package/dist/icons/generated/shard-27.cjs +2 -0
- package/dist/icons/generated/shard-27.cjs.map +1 -0
- package/dist/icons/generated/shard-27.js +48 -0
- package/dist/icons/generated/shard-27.js.map +1 -0
- package/dist/icons/generated/shard-28.cjs +2 -0
- package/dist/icons/generated/shard-28.cjs.map +1 -0
- package/dist/icons/generated/shard-28.js +48 -0
- package/dist/icons/generated/shard-28.js.map +1 -0
- package/dist/icons/generated/shard-29.cjs +2 -0
- package/dist/icons/generated/shard-29.cjs.map +1 -0
- package/dist/icons/generated/shard-29.js +48 -0
- package/dist/icons/generated/shard-29.js.map +1 -0
- package/dist/icons/generated/shard-30.cjs +2 -0
- package/dist/icons/generated/shard-30.cjs.map +1 -0
- package/dist/icons/generated/shard-30.js +48 -0
- package/dist/icons/generated/shard-30.js.map +1 -0
- package/dist/icons/generated/shard-31.cjs +2 -0
- package/dist/icons/generated/shard-31.cjs.map +1 -0
- package/dist/icons/generated/shard-31.js +48 -0
- package/dist/icons/generated/shard-31.js.map +1 -0
- package/dist/icons/generated/shard-32.cjs +2 -0
- package/dist/icons/generated/shard-32.cjs.map +1 -0
- package/dist/icons/generated/shard-32.js +48 -0
- package/dist/icons/generated/shard-32.js.map +1 -0
- package/dist/icons/generated/shard-33.cjs +2 -0
- package/dist/icons/generated/shard-33.cjs.map +1 -0
- package/dist/icons/generated/shard-33.js +48 -0
- package/dist/icons/generated/shard-33.js.map +1 -0
- package/dist/icons/generated/shard-34.cjs +2 -0
- package/dist/icons/generated/shard-34.cjs.map +1 -0
- package/dist/icons/generated/shard-34.js +48 -0
- package/dist/icons/generated/shard-34.js.map +1 -0
- package/dist/icons/generated/shard-35.cjs +2 -0
- package/dist/icons/generated/shard-35.cjs.map +1 -0
- package/dist/icons/generated/shard-35.js +48 -0
- package/dist/icons/generated/shard-35.js.map +1 -0
- package/dist/icons/generated/shard-36.cjs +2 -0
- package/dist/icons/generated/shard-36.cjs.map +1 -0
- package/dist/icons/generated/shard-36.js +48 -0
- package/dist/icons/generated/shard-36.js.map +1 -0
- package/dist/icons/generated/shard-37.cjs +2 -0
- package/dist/icons/generated/shard-37.cjs.map +1 -0
- package/dist/icons/generated/shard-37.js +48 -0
- package/dist/icons/generated/shard-37.js.map +1 -0
- package/dist/icons/generated/shard-38.cjs +2 -0
- package/dist/icons/generated/shard-38.cjs.map +1 -0
- package/dist/icons/generated/shard-38.js +48 -0
- package/dist/icons/generated/shard-38.js.map +1 -0
- package/dist/icons/generated/shard-39.cjs +2 -0
- package/dist/icons/generated/shard-39.cjs.map +1 -0
- package/dist/icons/generated/shard-39.js +48 -0
- package/dist/icons/generated/shard-39.js.map +1 -0
- package/dist/icons/generated/shard-40.cjs +2 -0
- package/dist/icons/generated/shard-40.cjs.map +1 -0
- package/dist/icons/generated/shard-40.js +48 -0
- package/dist/icons/generated/shard-40.js.map +1 -0
- package/dist/icons/generated/shard-41.cjs +2 -0
- package/dist/icons/generated/shard-41.cjs.map +1 -0
- package/dist/icons/generated/shard-41.js +48 -0
- package/dist/icons/generated/shard-41.js.map +1 -0
- package/dist/icons/generated/shard-42.cjs +2 -0
- package/dist/icons/generated/shard-42.cjs.map +1 -0
- package/dist/icons/generated/shard-42.js +48 -0
- package/dist/icons/generated/shard-42.js.map +1 -0
- package/dist/icons/generated/shard-43.cjs +2 -0
- package/dist/icons/generated/shard-43.cjs.map +1 -0
- package/dist/icons/generated/shard-43.js +48 -0
- package/dist/icons/generated/shard-43.js.map +1 -0
- package/dist/icons/generated/shard-44.cjs +2 -0
- package/dist/icons/generated/shard-44.cjs.map +1 -0
- package/dist/icons/generated/shard-44.js +15 -0
- package/dist/icons/generated/shard-44.js.map +1 -0
- package/dist/icons/material-symbols.cjs +1 -1
- package/dist/icons/material-symbols.cjs.map +1 -1
- package/dist/icons/material-symbols.js +109 -1
- package/dist/icons/material-symbols.js.map +1 -1
- package/dist/icons/normalize-icon-name.cjs +2 -0
- package/dist/icons/normalize-icon-name.cjs.map +1 -0
- package/dist/icons/normalize-icon-name.js +9 -0
- package/dist/icons/normalize-icon-name.js.map +1 -0
- package/dist/icons/shard-cache.cjs +1 -1
- package/dist/icons/shard-cache.cjs.map +1 -1
- package/dist/icons/shard-cache.js +85 -32
- package/dist/icons/shard-cache.js.map +1 -1
- package/dist/icons/validate-icon-name.cjs +2 -0
- package/dist/icons/validate-icon-name.cjs.map +1 -0
- package/dist/icons/validate-icon-name.js +11 -0
- package/dist/icons/validate-icon-name.js.map +1 -0
- package/dist/icons-virtual-id.d.ts +24 -0
- package/dist/icons-virtual.cjs +2 -0
- package/dist/icons-virtual.cjs.map +1 -0
- package/dist/icons-virtual.d.ts +30 -22
- package/dist/icons-virtual.js +6 -0
- package/dist/icons-virtual.js.map +1 -0
- package/dist/icons.cjs +1 -1
- package/dist/icons.d.ts +269 -32
- package/dist/icons.js +11 -7
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +95 -64
- package/dist/tempest-react-sdk.js +225 -226
- package/dist/utils/dev-mode.cjs.map +1 -1
- package/dist/utils/dev-mode.js.map +1 -1
- package/dist/vite/tempest-icons.cjs +4 -4
- package/dist/vite/tempest-icons.cjs.map +1 -1
- package/dist/vite/tempest-icons.js +26 -26
- package/dist/vite/tempest-icons.js.map +1 -1
- package/dist/vite.d.ts +1 -1
- package/package.json +5 -2
- package/dist/icons/generated/shard-a.cjs +0 -2
- package/dist/icons/generated/shard-a.cjs.map +0 -1
- package/dist/icons/generated/shard-a.js +0 -114
- package/dist/icons/generated/shard-a.js.map +0 -1
- package/dist/icons/generated/shard-b.cjs +0 -2
- package/dist/icons/generated/shard-b.cjs.map +0 -1
- package/dist/icons/generated/shard-b.js +0 -158
- package/dist/icons/generated/shard-b.js.map +0 -1
- package/dist/icons/generated/shard-c.cjs +0 -2
- package/dist/icons/generated/shard-c.cjs.map +0 -1
- package/dist/icons/generated/shard-c.js +0 -269
- package/dist/icons/generated/shard-c.js.map +0 -1
- package/dist/icons/generated/shard-d.cjs +0 -2
- package/dist/icons/generated/shard-d.cjs.map +0 -1
- package/dist/icons/generated/shard-d.js +0 -62
- package/dist/icons/generated/shard-d.js.map +0 -1
- package/dist/icons/generated/shard-e.cjs +0 -2
- package/dist/icons/generated/shard-e.cjs.map +0 -1
- package/dist/icons/generated/shard-e.js +0 -33
- package/dist/icons/generated/shard-e.js.map +0 -1
- package/dist/icons/generated/shard-f.cjs +0 -2
- package/dist/icons/generated/shard-f.cjs.map +0 -1
- package/dist/icons/generated/shard-f.js +0 -145
- package/dist/icons/generated/shard-f.js.map +0 -1
- package/dist/icons/generated/shard-g.cjs +0 -2
- package/dist/icons/generated/shard-g.cjs.map +0 -1
- package/dist/icons/generated/shard-g.js +0 -61
- package/dist/icons/generated/shard-g.js.map +0 -1
- package/dist/icons/generated/shard-h.cjs +0 -2
- package/dist/icons/generated/shard-h.cjs.map +0 -1
- package/dist/icons/generated/shard-h.js +0 -62
- package/dist/icons/generated/shard-h.js.map +0 -1
- package/dist/icons/generated/shard-i.cjs +0 -2
- package/dist/icons/generated/shard-i.cjs.map +0 -1
- package/dist/icons/generated/shard-i.js +0 -30
- package/dist/icons/generated/shard-i.js.map +0 -1
- package/dist/icons/generated/shard-j.cjs +0 -2
- package/dist/icons/generated/shard-j.cjs.map +0 -1
- package/dist/icons/generated/shard-j.js +0 -10
- package/dist/icons/generated/shard-j.js.map +0 -1
- package/dist/icons/generated/shard-k.cjs +0 -2
- package/dist/icons/generated/shard-k.cjs.map +0 -1
- package/dist/icons/generated/shard-k.js +0 -16
- package/dist/icons/generated/shard-k.js.map +0 -1
- package/dist/icons/generated/shard-l.cjs +0 -2
- package/dist/icons/generated/shard-l.cjs.map +0 -1
- package/dist/icons/generated/shard-l.js +0 -92
- package/dist/icons/generated/shard-l.js.map +0 -1
- package/dist/icons/generated/shard-m.cjs +0 -2
- package/dist/icons/generated/shard-m.cjs.map +0 -1
- package/dist/icons/generated/shard-m.js +0 -143
- package/dist/icons/generated/shard-m.js.map +0 -1
- package/dist/icons/generated/shard-n.cjs +0 -2
- package/dist/icons/generated/shard-n.cjs.map +0 -1
- package/dist/icons/generated/shard-n.js +0 -24
- package/dist/icons/generated/shard-n.js.map +0 -1
- package/dist/icons/generated/shard-o.cjs +0 -2
- package/dist/icons/generated/shard-o.cjs.map +0 -1
- package/dist/icons/generated/shard-o.js +0 -17
- package/dist/icons/generated/shard-o.js.map +0 -1
- package/dist/icons/generated/shard-p.cjs +0 -2
- package/dist/icons/generated/shard-p.cjs.map +0 -1
- package/dist/icons/generated/shard-p.js +0 -114
- package/dist/icons/generated/shard-p.js.map +0 -1
- package/dist/icons/generated/shard-q.cjs +0 -2
- package/dist/icons/generated/shard-q.cjs.map +0 -1
- package/dist/icons/generated/shard-q.js +0 -10
- package/dist/icons/generated/shard-q.js.map +0 -1
- package/dist/icons/generated/shard-r.cjs +0 -2
- package/dist/icons/generated/shard-r.cjs.map +0 -1
- package/dist/icons/generated/shard-r.js +0 -79
- package/dist/icons/generated/shard-r.js.map +0 -1
- package/dist/icons/generated/shard-s.cjs +0 -2
- package/dist/icons/generated/shard-s.cjs.map +0 -1
- package/dist/icons/generated/shard-s.js +0 -256
- package/dist/icons/generated/shard-s.js.map +0 -1
- package/dist/icons/generated/shard-t.cjs +0 -2
- package/dist/icons/generated/shard-t.cjs.map +0 -1
- package/dist/icons/generated/shard-t.js +0 -109
- package/dist/icons/generated/shard-t.js.map +0 -1
- package/dist/icons/generated/shard-u.cjs +0 -2
- package/dist/icons/generated/shard-u.cjs.map +0 -1
- package/dist/icons/generated/shard-u.js +0 -50
- package/dist/icons/generated/shard-u.js.map +0 -1
- package/dist/icons/generated/shard-v.cjs +0 -2
- package/dist/icons/generated/shard-v.cjs.map +0 -1
- package/dist/icons/generated/shard-v.js +0 -30
- package/dist/icons/generated/shard-v.js.map +0 -1
- package/dist/icons/generated/shard-w.cjs +0 -2
- package/dist/icons/generated/shard-w.cjs.map +0 -1
- package/dist/icons/generated/shard-w.js +0 -48
- package/dist/icons/generated/shard-w.js.map +0 -1
- package/dist/icons/generated/shard-x.cjs +0 -2
- package/dist/icons/generated/shard-x.cjs.map +0 -1
- package/dist/icons/generated/shard-x.js +0 -10
- package/dist/icons/generated/shard-x.js.map +0 -1
- package/dist/icons/generated/shard-z.cjs +0 -2
- package/dist/icons/generated/shard-z.cjs.map +0 -1
- package/dist/icons/generated/shard-z.js +0 -25
- package/dist/icons/generated/shard-z.js.map +0 -1
package/dist/http/errors.js
CHANGED
|
@@ -4,9 +4,10 @@ var e = class extends Error {
|
|
|
4
4
|
detail;
|
|
5
5
|
code;
|
|
6
6
|
requestId;
|
|
7
|
+
fields;
|
|
7
8
|
body;
|
|
8
9
|
constructor(e) {
|
|
9
|
-
super(e.detail), this.name = "TempestApiError", this.status = e.status, this.detail = e.detail, this.code = e.code, this.requestId = e.requestId, this.body = e.body;
|
|
10
|
+
super(e.detail), this.name = "TempestApiError", this.status = e.status, this.detail = e.detail, this.code = e.code, this.requestId = e.requestId, this.fields = e.fields, this.body = e.body;
|
|
10
11
|
}
|
|
11
12
|
};
|
|
12
13
|
function t(e) {
|
|
@@ -24,37 +25,53 @@ function r(e) {
|
|
|
24
25
|
let t = e.filter((e) => typeof e == "string" || typeof e == "number").filter((e, t) => !(t === 0 && n.has(String(e))));
|
|
25
26
|
return t.length > 0 ? t.join(".") : void 0;
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
var i = 4;
|
|
29
|
+
function a(e) {
|
|
30
|
+
if (!Array.isArray(e)) return;
|
|
31
|
+
let t = {};
|
|
32
|
+
for (let n of e) {
|
|
33
|
+
if (typeof n != "object" || !n) continue;
|
|
34
|
+
let e = n, i = r(e.loc);
|
|
35
|
+
if (i === void 0 || i in t) continue;
|
|
36
|
+
let a = o(e.msg) ?? o(e.message);
|
|
37
|
+
a !== void 0 && (t[i] = a);
|
|
38
|
+
}
|
|
39
|
+
return Object.keys(t).length > 0 ? t : void 0;
|
|
40
|
+
}
|
|
41
|
+
function o(e, t = 0) {
|
|
28
42
|
if (e != null) {
|
|
29
43
|
if (typeof e == "string") return e === "" ? void 0 : e;
|
|
30
44
|
if (typeof e == "number" || typeof e == "boolean") return String(e);
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
let
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
if (!(t >= i)) {
|
|
46
|
+
if (Array.isArray(e)) {
|
|
47
|
+
let n = e.map((e) => {
|
|
48
|
+
let n = o(e, t + 1);
|
|
49
|
+
if (n === void 0) return;
|
|
50
|
+
let i = typeof e == "object" && e ? r(e.loc) : void 0;
|
|
51
|
+
return i === void 0 ? n : `${i}: ${n}`;
|
|
52
|
+
}).filter((e) => e !== void 0);
|
|
53
|
+
return n.length > 0 ? n.join("; ") : void 0;
|
|
54
|
+
}
|
|
55
|
+
if (typeof e == "object") {
|
|
56
|
+
let n = e;
|
|
57
|
+
return o(n.msg, t + 1) ?? o(n.message, t + 1) ?? o(n.detail, t + 1);
|
|
58
|
+
}
|
|
43
59
|
}
|
|
44
60
|
}
|
|
45
61
|
}
|
|
46
|
-
function
|
|
47
|
-
let
|
|
62
|
+
function s(e, t, n, r) {
|
|
63
|
+
let i = typeof t == "object" && t ? t : null, s = o(i?.detail) ?? o(i?.message) ?? `Erro ${e}`, l = typeof i?.code == "string" ? i.code : void 0, u = typeof i?.details == "object" && i.details !== null ? i.details : null;
|
|
48
64
|
return {
|
|
49
65
|
status: e,
|
|
50
66
|
detail: s,
|
|
51
|
-
code:
|
|
52
|
-
requestId: (typeof
|
|
53
|
-
retryAfter:
|
|
67
|
+
code: l,
|
|
68
|
+
requestId: (typeof u?.request_id == "string" ? u.request_id : void 0) ?? n?.get("X-Request-ID") ?? r ?? void 0 ?? void 0,
|
|
69
|
+
retryAfter: c(n?.get("Retry-After")),
|
|
70
|
+
fields: a(i?.detail),
|
|
54
71
|
body: t
|
|
55
72
|
};
|
|
56
73
|
}
|
|
57
|
-
function
|
|
74
|
+
function c(e) {
|
|
58
75
|
if (!e) return;
|
|
59
76
|
let t = e.trim();
|
|
60
77
|
if (/^\d+$/.test(t)) return Number(t);
|
|
@@ -62,6 +79,6 @@ function o(e) {
|
|
|
62
79
|
if (!Number.isNaN(n)) return Math.max(0, Math.round((n - Date.now()) / 1e3));
|
|
63
80
|
}
|
|
64
81
|
//#endregion
|
|
65
|
-
export { e as TempestApiError,
|
|
82
|
+
export { e as TempestApiError, s as buildApiError, t as isApiError, c as parseRetryAfter };
|
|
66
83
|
|
|
67
84
|
//# sourceMappingURL=errors.js.map
|
package/dist/http/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../../src/http/errors.ts"],"sourcesContent":["import type { ApiError } from \"./types\";\n\n/**\n * Error thrown by {@link createApiClient} / {@link uploadWithProgress} on a\n * non-2xx response. Mirrors the Tempest FastAPI SDK error envelope\n * (`{ detail, code, details.request_id }`) so callers get a typed `code` and a\n * `requestId` for log correlation, while still being a real `Error` (stack\n * trace, `instanceof Error`).\n *\n * @example\n * try {\n * await api.post(\"/users\", { body });\n * } catch (err) {\n * if (isApiError(err) && err.code === \"EMAIL_TAKEN\") {\n * showFieldError(\"email\", err.detail);\n * }\n * }\n */\nexport class TempestApiError extends Error implements ApiError {\n readonly status: number;\n readonly detail: string;\n readonly code?: string;\n readonly requestId?: string;\n readonly body?: unknown;\n\n constructor(init: ApiError) {\n super(init.detail);\n this.name = \"TempestApiError\";\n this.status = init.status;\n this.detail = init.detail;\n this.code = init.code;\n this.requestId = init.requestId;\n this.body = init.body;\n }\n}\n\n/**\n * Type guard for the {@link ApiError} shape. Matches both {@link TempestApiError}\n * instances and plain objects carrying `status` + `detail`.\n *\n * @param error - The unknown value (typically a caught error).\n * @returns Whether `error` conforms to the `ApiError` contract.\n */\nexport function isApiError(error: unknown): error is ApiError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n typeof (error as ApiError).status === \"number\" &&\n typeof (error as ApiError).detail === \"string\"\n );\n}\n\n/**\n * Location prefixes FastAPI puts at the head of a validation error's `loc`,\n * naming the part of the request rather than the field. Dropped from the\n * rendered path, so `[\"body\", \"email\"]` reads as `email`.\n */\nconst LOC_ROOTS: ReadonlySet<string> = new Set([\"body\", \"query\", \"path\", \"header\", \"cookie\"]);\n\n/**\n * Render a FastAPI validation error's `loc` tuple as a dotted field path.\n *\n * @param loc - The raw `loc` value from one validation error entry.\n * @returns The dotted path (`\"items.0.price\"`), or undefined when `loc` carries\n * nothing addressable.\n */\nfunction formatLoc(loc: unknown): string | undefined {\n if (!Array.isArray(loc)) return undefined;\n const parts = loc\n .filter(\n (part): part is string | number => typeof part === \"string\" || typeof part === \"number\",\n )\n .filter((part, index) => !(index === 0 && LOC_ROOTS.has(String(part))));\n return parts.length > 0 ? parts.join(\".\") : undefined;\n}\n\n/**\n * Collapse a backend `detail` of any shape into a single readable line.\n *\n * FastAPI answers a `422` with `detail` as a **list** of\n * `{ loc, msg, type }` entries, not a string. Passing that through `String()`\n * yields `\"[object Object]\"` — an error message that tells the user nothing and\n * hides which field failed. Each entry becomes `\"<field>: <msg>\"` and the\n * entries are joined with `\"; \"`; a nested object is read through its\n * `msg`/`message`/`detail` string.\n *\n * @param raw - The `detail` (or `message`) value from the error body.\n * @returns The rendered message, or undefined when nothing readable is there —\n * letting the caller fall back to the synthetic `Erro <status>`.\n */\nfunction normalizeDetail(raw: unknown): string | undefined {\n if (raw === null || raw === undefined) return undefined;\n if (typeof raw === \"string\") return raw === \"\" ? undefined : raw;\n if (typeof raw === \"number\" || typeof raw === \"boolean\") return String(raw);\n\n if (Array.isArray(raw)) {\n const lines = raw\n .map((entry) => {\n const message = normalizeDetail(entry);\n if (message === undefined) return undefined;\n const field =\n typeof entry === \"object\" && entry !== null\n ? formatLoc((entry as Record<string, unknown>).loc)\n : undefined;\n return field === undefined ? message : `${field}: ${message}`;\n })\n .filter((line): line is string => line !== undefined);\n return lines.length > 0 ? lines.join(\"; \") : undefined;\n }\n\n if (typeof raw === \"object\") {\n const entry = raw as Record<string, unknown>;\n return (\n normalizeDetail(entry.msg) ??\n normalizeDetail(entry.message) ??\n normalizeDetail(entry.detail)\n );\n }\n\n return undefined;\n}\n\n/**\n * Parse an error body + response into the Tempest {@link ApiError} envelope.\n *\n * Reads `detail`/`message`, the programmatic `code`, and the correlation id\n * from `details.request_id` (falling back to the `X-Request-ID` header, then\n * the id the client sent).\n *\n * A `422` from FastAPI carries `detail` as a list of `{ loc, msg, type }`\n * entries, so it is flattened to `\"<field>: <msg>; <field>: <msg>\"` instead of\n * being stringified into `\"[object Object]\"`. The untouched list stays on\n * `body` for callers that map errors onto form fields.\n *\n * @param status - HTTP status code.\n * @param body - The parsed error body (object, string, or null).\n * @param headers - The response headers (for the `X-Request-ID` fallback).\n * @param sentRequestId - The id the client sent on the request, if any.\n * @returns A fully-populated `ApiError`.\n *\n * @tempest-limits param-count — the arguments are the response as it arrives\n * (`status`, `body`, `headers`) plus the id the request was sent with, and they are\n * passed at exactly one place: the client's response path. Exported from the package\n * root, so the rewrite would be breaking for callers that build their own errors.\n */\nexport function buildApiError(\n status: number,\n body: unknown,\n headers?: Headers | { get(name: string): string | null },\n sentRequestId?: string,\n): ApiError {\n const obj =\n typeof body === \"object\" && body !== null ? (body as Record<string, unknown>) : null;\n const detail =\n normalizeDetail(obj?.detail) ?? normalizeDetail(obj?.message) ?? `Erro ${status}`;\n const code = typeof obj?.code === \"string\" ? obj.code : undefined;\n const details =\n typeof obj?.details === \"object\" && obj.details !== null\n ? (obj.details as Record<string, unknown>)\n : null;\n const requestId =\n (typeof details?.request_id === \"string\" ? details.request_id : undefined) ??\n headers?.get(\"X-Request-ID\") ??\n sentRequestId ??\n undefined;\n\n return {\n status,\n detail,\n code,\n requestId: requestId ?? undefined,\n retryAfter: parseRetryAfter(headers?.get(\"Retry-After\")),\n body,\n };\n}\n\n/**\n * Parse a `Retry-After` header into seconds. Accepts a delta-seconds integer\n * (`\"120\"`) or an HTTP-date (`\"Wed, 21 Oct 2015 07:28:00 GMT\"`).\n *\n * @param value - The raw header value, or null.\n * @returns The delay in seconds (>= 0), or undefined when absent/unparseable.\n */\nexport function parseRetryAfter(value: string | null | undefined): number | undefined {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (/^\\d+$/.test(trimmed)) return Number(trimmed);\n const when = Date.parse(trimmed);\n if (Number.isNaN(when)) return undefined;\n return Math.max(0, Math.round((when - Date.now()) / 1000));\n}\n"],"mappings":";AAkBA,IAAa,IAAb,cAAqC,MAA0B;CAC3D;CACA;CACA;CACA;CACA;CAEA,YAAY,GAAgB;EAOxB,AANA,MAAM,EAAK,MAAM,GACjB,KAAK,OAAO,mBACZ,KAAK,SAAS,EAAK,QACnB,KAAK,SAAS,EAAK,QACnB,KAAK,OAAO,EAAK,MACjB,KAAK,YAAY,EAAK,WACtB,KAAK,OAAO,EAAK;CACrB;AACJ;AASA,SAAgB,EAAW,GAAmC;CAC1D,OACI,OAAO,KAAU,cACjB,KACA,OAAQ,EAAmB,UAAW,YACtC,OAAQ,EAAmB,UAAW;AAE9C;AAOA,IAAM,oBAAiC,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAQ;CAAU;AAAQ,CAAC;AAS5F,SAAS,EAAU,GAAkC;CACjD,IAAI,CAAC,MAAM,QAAQ,CAAG,GAAG;CACzB,IAAM,IAAQ,EACT,QACI,MAAkC,OAAO,KAAS,YAAY,OAAO,KAAS,QACnF,CAAC,CACA,QAAQ,GAAM,MAAU,EAAE,MAAU,KAAK,EAAU,IAAI,OAAO,CAAI,CAAC,EAAE;CAC1E,OAAO,EAAM,SAAS,IAAI,EAAM,KAAK,GAAG,IAAI,KAAA;AAChD;AAgBA,SAAS,EAAgB,GAAkC;CACnD,SAAQ,MACZ;MAAI,OAAO,KAAQ,UAAU,OAAO,MAAQ,KAAK,KAAA,IAAY;EAC7D,IAAI,OAAO,KAAQ,YAAY,OAAO,KAAQ,WAAW,OAAO,OAAO,CAAG;EAE1E,IAAI,MAAM,QAAQ,CAAG,GAAG;GACpB,IAAM,IAAQ,EACT,KAAK,MAAU;IACZ,IAAM,IAAU,EAAgB,CAAK;IACrC,IAAI,MAAY,KAAA,GAAW;IAC3B,IAAM,IACF,OAAO,KAAU,YAAY,IACvB,EAAW,EAAkC,GAAG,IAChD,KAAA;IACV,OAAO,MAAU,KAAA,IAAY,IAAU,GAAG,EAAM,IAAI;GACxD,CAAC,CAAC,CACD,QAAQ,MAAyB,MAAS,KAAA,CAAS;GACxD,OAAO,EAAM,SAAS,IAAI,EAAM,KAAK,IAAI,IAAI,KAAA;EACjD;EAEA,IAAI,OAAO,KAAQ,UAAU;GACzB,IAAM,IAAQ;GACd,OACI,EAAgB,EAAM,GAAG,KACzB,EAAgB,EAAM,OAAO,KAC7B,EAAgB,EAAM,MAAM;EAEpC;CAzB6D;AA4BjE;AAyBA,SAAgB,EACZ,GACA,GACA,GACA,GACQ;CACR,IAAM,IACF,OAAO,KAAS,YAAY,IAAiB,IAAmC,MAC9E,IACF,EAAgB,GAAK,MAAM,KAAK,EAAgB,GAAK,OAAO,KAAK,QAAQ,KACvE,IAAO,OAAO,GAAK,QAAS,WAAW,EAAI,OAAO,KAAA,GAClD,IACF,OAAO,GAAK,WAAY,YAAY,EAAI,YAAY,OAC7C,EAAI,UACL;CAOV,OAAO;EACH;EACA;EACA;EACA,YATC,OAAO,GAAS,cAAe,WAAW,EAAQ,aAAa,KAAA,MAChE,GAAS,IAAI,cAAc,KAC3B,KACA,KAAA,KAMwB,KAAA;EACxB,YAAY,EAAgB,GAAS,IAAI,aAAa,CAAC;EACvD;CACJ;AACJ;AASA,SAAgB,EAAgB,GAAsD;CAClF,IAAI,CAAC,GAAO;CACZ,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,QAAQ,KAAK,CAAO,GAAG,OAAO,OAAO,CAAO;CAChD,IAAM,IAAO,KAAK,MAAM,CAAO;CAC3B,YAAO,MAAM,CAAI,GACrB,OAAO,KAAK,IAAI,GAAG,KAAK,OAAO,IAAO,KAAK,IAAI,KAAK,GAAI,CAAC;AAC7D"}
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../../src/http/errors.ts"],"sourcesContent":["import type { ApiError } from \"./types\";\n\n/**\n * Error thrown by {@link createApiClient} / {@link uploadWithProgress} on a\n * non-2xx response. Mirrors the Tempest FastAPI SDK error envelope\n * (`{ detail, code, details.request_id }`) so callers get a typed `code` and a\n * `requestId` for log correlation, while still being a real `Error` (stack\n * trace, `instanceof Error`).\n *\n * @example\n * try {\n * await api.post(\"/users\", { body });\n * } catch (err) {\n * if (isApiError(err) && err.code === \"EMAIL_TAKEN\") {\n * showFieldError(\"email\", err.detail);\n * }\n * }\n */\nexport class TempestApiError extends Error implements ApiError {\n readonly status: number;\n readonly detail: string;\n readonly code?: string;\n readonly requestId?: string;\n readonly fields?: Record<string, string>;\n readonly body?: unknown;\n\n constructor(init: ApiError) {\n super(init.detail);\n this.name = \"TempestApiError\";\n this.status = init.status;\n this.detail = init.detail;\n this.code = init.code;\n this.requestId = init.requestId;\n this.fields = init.fields;\n this.body = init.body;\n }\n}\n\n/**\n * Type guard for the {@link ApiError} shape. Matches both {@link TempestApiError}\n * instances and plain objects carrying `status` + `detail`.\n *\n * @param error - The unknown value (typically a caught error).\n * @returns Whether `error` conforms to the `ApiError` contract.\n */\nexport function isApiError(error: unknown): error is ApiError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n typeof (error as ApiError).status === \"number\" &&\n typeof (error as ApiError).detail === \"string\"\n );\n}\n\n/**\n * Location prefixes FastAPI puts at the head of a validation error's `loc`,\n * naming the part of the request rather than the field. Dropped from the\n * rendered path, so `[\"body\", \"email\"]` reads as `email`.\n */\nconst LOC_ROOTS: ReadonlySet<string> = new Set([\"body\", \"query\", \"path\", \"header\", \"cookie\"]);\n\n/**\n * Render a FastAPI validation error's `loc` tuple as a dotted field path.\n *\n * @param loc - The raw `loc` value from one validation error entry.\n * @returns The dotted path (`\"items.0.price\"`), or undefined when `loc` carries\n * nothing addressable.\n */\nfunction formatLoc(loc: unknown): string | undefined {\n if (!Array.isArray(loc)) return undefined;\n const parts = loc\n .filter(\n (part): part is string | number => typeof part === \"string\" || typeof part === \"number\",\n )\n .filter((part, index) => !(index === 0 && LOC_ROOTS.has(String(part))));\n return parts.length > 0 ? parts.join(\".\") : undefined;\n}\n\n/**\n * How deep {@link normalizeDetail} follows a nested `detail` before giving up.\n *\n * A real envelope needs two or three levels: the list, an entry, the entry's\n * own `detail`. The cap exists because the body is untrusted input arriving on\n * the error path — a response nesting `{\"detail\":{\"detail\":…}}` twenty thousand\n * deep (a 220 KB body) overflowed the stack, and a `RangeError` thrown while\n * *building* the error is worse than the error: the caller's `catch` stops\n * receiving a `TempestApiError`, so `isApiError` is false, `describeApiError`\n * has nothing to read and the `401` handling never runs.\n */\nconst MAX_DETAIL_DEPTH = 4;\n\n/**\n * Pull field-level messages out of a validation `detail` list.\n *\n * FastAPI's `422` body is `detail: [{ loc, msg, type }]`, which is exactly what\n * a form needs and exactly what the flattened `detail` string destroys. Only the\n * top level is read: a validation error names one field per entry, and following\n * nesting here would invent paths the backend never sent.\n *\n * @param raw - The `detail` value from the error body.\n * @returns Field path to message, or undefined when the body is not a\n * validation list (or carries no entry naming a field).\n */\nfunction collectFields(raw: unknown): Record<string, string> | undefined {\n if (!Array.isArray(raw)) return undefined;\n\n const fields: Record<string, string> = {};\n for (const entry of raw) {\n if (typeof entry !== \"object\" || entry === null) continue;\n const record = entry as Record<string, unknown>;\n const field = formatLoc(record.loc);\n if (field === undefined || field in fields) continue;\n const message = normalizeDetail(record.msg) ?? normalizeDetail(record.message);\n if (message === undefined) continue;\n fields[field] = message;\n }\n\n return Object.keys(fields).length > 0 ? fields : undefined;\n}\n\n/**\n * Collapse a backend `detail` of any shape into a single readable line.\n *\n * FastAPI answers a `422` with `detail` as a **list** of\n * `{ loc, msg, type }` entries, not a string. Passing that through `String()`\n * yields `\"[object Object]\"` — an error message that tells the user nothing and\n * hides which field failed. Each entry becomes `\"<field>: <msg>\"` and the\n * entries are joined with `\"; \"`; a nested object is read through its\n * `msg`/`message`/`detail` string.\n *\n * @param raw - The `detail` (or `message`) value from the error body.\n * @param depth - Current nesting level. Past {@link MAX_DETAIL_DEPTH} the value\n * is treated as unreadable instead of followed further.\n * @returns The rendered message, or undefined when nothing readable is there —\n * letting the caller fall back to the synthetic `Erro <status>`.\n */\nfunction normalizeDetail(raw: unknown, depth: number = 0): string | undefined {\n if (raw === null || raw === undefined) return undefined;\n if (typeof raw === \"string\") return raw === \"\" ? undefined : raw;\n if (typeof raw === \"number\" || typeof raw === \"boolean\") return String(raw);\n if (depth >= MAX_DETAIL_DEPTH) return undefined;\n\n if (Array.isArray(raw)) {\n const lines = raw\n .map((entry) => {\n const message = normalizeDetail(entry, depth + 1);\n if (message === undefined) return undefined;\n const field =\n typeof entry === \"object\" && entry !== null\n ? formatLoc((entry as Record<string, unknown>).loc)\n : undefined;\n return field === undefined ? message : `${field}: ${message}`;\n })\n .filter((line): line is string => line !== undefined);\n return lines.length > 0 ? lines.join(\"; \") : undefined;\n }\n\n if (typeof raw === \"object\") {\n const entry = raw as Record<string, unknown>;\n return (\n normalizeDetail(entry.msg, depth + 1) ??\n normalizeDetail(entry.message, depth + 1) ??\n normalizeDetail(entry.detail, depth + 1)\n );\n }\n\n return undefined;\n}\n\n/**\n * Parse an error body + response into the Tempest {@link ApiError} envelope.\n *\n * Reads `detail`/`message`, the programmatic `code`, and the correlation id\n * from `details.request_id` (falling back to the `X-Request-ID` header, then\n * the id the client sent).\n *\n * A `422` from FastAPI carries `detail` as a list of `{ loc, msg, type }`\n * entries, so it is flattened to `\"<field>: <msg>; <field>: <msg>\"` instead of\n * being stringified into `\"[object Object]\"`, and the same entries are indexed\n * on `fields` (`{ email: \"Field required\" }`) for a form to consume without\n * parsing that line back apart. The untouched body stays on `body`.\n *\n * That flattened `detail` is developer-facing: it carries the backend's field\n * paths and the validator's own wording. `describeApiError` knows not to show it\n * to a person when `fields` is set.\n *\n * @param status - HTTP status code.\n * @param body - The parsed error body (object, string, or null).\n * @param headers - The response headers (for the `X-Request-ID` fallback).\n * @param sentRequestId - The id the client sent on the request, if any.\n * @returns A fully-populated `ApiError`.\n *\n * @tempest-limits param-count — the arguments are the response as it arrives\n * (`status`, `body`, `headers`) plus the id the request was sent with, and they are\n * passed at exactly one place: the client's response path. Exported from the package\n * root, so the rewrite would be breaking for callers that build their own errors.\n */\nexport function buildApiError(\n status: number,\n body: unknown,\n headers?: Headers | { get(name: string): string | null },\n sentRequestId?: string,\n): ApiError {\n const obj =\n typeof body === \"object\" && body !== null ? (body as Record<string, unknown>) : null;\n const detail =\n normalizeDetail(obj?.detail) ?? normalizeDetail(obj?.message) ?? `Erro ${status}`;\n const code = typeof obj?.code === \"string\" ? obj.code : undefined;\n const details =\n typeof obj?.details === \"object\" && obj.details !== null\n ? (obj.details as Record<string, unknown>)\n : null;\n const requestId =\n (typeof details?.request_id === \"string\" ? details.request_id : undefined) ??\n headers?.get(\"X-Request-ID\") ??\n sentRequestId ??\n undefined;\n\n return {\n status,\n detail,\n code,\n requestId: requestId ?? undefined,\n retryAfter: parseRetryAfter(headers?.get(\"Retry-After\")),\n fields: collectFields(obj?.detail),\n body,\n };\n}\n\n/**\n * Parse a `Retry-After` header into seconds. Accepts a delta-seconds integer\n * (`\"120\"`) or an HTTP-date (`\"Wed, 21 Oct 2015 07:28:00 GMT\"`).\n *\n * @param value - The raw header value, or null.\n * @returns The delay in seconds (>= 0), or undefined when absent/unparseable.\n */\nexport function parseRetryAfter(value: string | null | undefined): number | undefined {\n if (!value) return undefined;\n const trimmed = value.trim();\n if (/^\\d+$/.test(trimmed)) return Number(trimmed);\n const when = Date.parse(trimmed);\n if (Number.isNaN(when)) return undefined;\n return Math.max(0, Math.round((when - Date.now()) / 1000));\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./describe-api-error.cjs"),t=require("../i18n/I18nProvider.cjs");let n=require("react");function r(){let r=t.useOptionalI18n()?.t;return(0,n.useCallback)((t,n)=>{
|
|
1
|
+
const e=require("./describe-api-error.cjs"),t=require("../i18n/I18nProvider.cjs");let n=require("react");function r(t,n,r){let i=t?.(n);return i&&i!==n?i:e.DEFAULT_API_ERROR_STRINGS[r]}function i(){let i=t.useOptionalI18n()?.t;return(0,n.useCallback)((t,n)=>e.describeApiError(t,n,{offline:r(i,e.API_ERROR_OFFLINE_KEY,`offline`),validation:r(i,e.API_ERROR_VALIDATION_KEY,`validation`)}),[i])}exports.useDescribeApiError=i;
|
|
2
2
|
//# sourceMappingURL=use-describe-api-error.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-describe-api-error.cjs","names":[],"sources":["../../src/http/use-describe-api-error.ts"],"sourcesContent":["import { useCallback } from \"react\";\n\nimport { useOptionalI18n } from \"../i18n/I18nProvider\";\nimport {\n API_ERROR_OFFLINE_KEY,\n DEFAULT_API_ERROR_STRINGS,\n describeApiError,\n} from \"./describe-api-error\";\n\n/**\n * {@link describeApiError} with its fixed sentences resolved through the active\n * `I18nProvider`.\n *\n * The funnel is not duplicated — this hook only supplies the strings and calls\n * the pure function. Which is also why both exist: the pure one runs in an\n * interceptor or a logger, where there is no React tree to read a context from,\n * and this one runs in a component without every caller passing translations\n * down by hand.\n *\n * Works with no provider at all: i18n is opt-in in this SDK, so a missing\n * provider — or a catalog that never defined `tempest.error.offline` — falls\n * back to the pt-BR default rather than crashing or printing the raw key.\n *\n * @example\n * const describe = useDescribeApiError();\n * const { mutate } = useMutation({\n * mutationFn: save,\n * onError: (error) => toast(describe(error, t(\"orders.saveFailed\"))),\n * });\n *\n * @returns A stable `(error, fallback) => string` function.\n */\nexport function useDescribeApiError(): (error: unknown, fallback: string) => string {\n const i18n = useOptionalI18n();\n const translate = i18n?.t;\n\n return useCallback(\n (error: unknown, fallback: string) => {\n
|
|
1
|
+
{"version":3,"file":"use-describe-api-error.cjs","names":[],"sources":["../../src/http/use-describe-api-error.ts"],"sourcesContent":["import { useCallback } from \"react\";\n\nimport { useOptionalI18n } from \"../i18n/I18nProvider\";\nimport {\n API_ERROR_OFFLINE_KEY,\n API_ERROR_VALIDATION_KEY,\n DEFAULT_API_ERROR_STRINGS,\n describeApiError,\n} from \"./describe-api-error\";\n\n/**\n * {@link describeApiError} with its fixed sentences resolved through the active\n * `I18nProvider`.\n *\n * The funnel is not duplicated — this hook only supplies the strings and calls\n * the pure function. Which is also why both exist: the pure one runs in an\n * interceptor or a logger, where there is no React tree to read a context from,\n * and this one runs in a component without every caller passing translations\n * down by hand.\n *\n * Works with no provider at all: i18n is opt-in in this SDK, so a missing\n * provider — or a catalog that never defined `tempest.error.offline` — falls\n * back to the pt-BR default rather than crashing or printing the raw key.\n *\n * @example\n * const describe = useDescribeApiError();\n * const { mutate } = useMutation({\n * mutationFn: save,\n * onError: (error) => toast(describe(error, t(\"orders.saveFailed\"))),\n * });\n *\n * @returns A stable `(error, fallback) => string` function.\n */\n/**\n * Look one sentence up in the active catalog, falling back to the pt-BR default.\n *\n * `t` returns the key itself on a miss, so the identity check is what separates\n * \"the catalog answered\" from \"the catalog has no such key\" — printing\n * `tempest.error.validation` at a user is worse than printing pt-BR at them.\n *\n * @param translate - The active catalog's `t`, if any provider is mounted.\n * @param key - The translation key to look up.\n * @param fallbackKey - Which {@link DEFAULT_API_ERROR_STRINGS} entry to use on a miss.\n * @returns The sentence to hand to `describeApiError`.\n */\nfunction resolve(\n translate: ((key: string) => string) | undefined,\n key: string,\n fallbackKey: keyof typeof DEFAULT_API_ERROR_STRINGS,\n): string {\n const translated = translate?.(key);\n return translated && translated !== key ? translated : DEFAULT_API_ERROR_STRINGS[fallbackKey];\n}\n\nexport function useDescribeApiError(): (error: unknown, fallback: string) => string {\n const i18n = useOptionalI18n();\n const translate = i18n?.t;\n\n return useCallback(\n (error: unknown, fallback: string) => {\n return describeApiError(error, fallback, {\n offline: resolve(translate, API_ERROR_OFFLINE_KEY, \"offline\"),\n validation: resolve(translate, API_ERROR_VALIDATION_KEY, \"validation\"),\n });\n },\n [translate],\n );\n}\n"],"mappings":"yGA6CA,SAAS,EACL,EACA,EACA,EACM,CACN,IAAM,EAAa,IAAY,CAAG,EAClC,OAAO,GAAc,IAAe,EAAM,EAAa,EAAA,0BAA0B,EACrF,CAEA,SAAgB,GAAoE,CAEhF,IAAM,EADO,EAAA,gBACK,CAAA,EAAM,EAExB,OAAA,EAAO,EAAA,YAAA,EACF,EAAgB,IACN,EAAA,iBAAiB,EAAO,EAAU,CACrC,QAAS,EAAQ,EAAW,EAAA,sBAAuB,SAAS,EAC5D,WAAY,EAAQ,EAAW,EAAA,yBAA0B,YAAY,CACzE,CAAC,EAEL,CAAC,CAAS,CACd,CACJ"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { API_ERROR_OFFLINE_KEY as e,
|
|
2
|
-
import { useOptionalI18n as
|
|
3
|
-
import { useCallback as
|
|
1
|
+
import { API_ERROR_OFFLINE_KEY as e, API_ERROR_VALIDATION_KEY as t, DEFAULT_API_ERROR_STRINGS as n, describeApiError as r } from "./describe-api-error.js";
|
|
2
|
+
import { useOptionalI18n as i } from "../i18n/I18nProvider.js";
|
|
3
|
+
import { useCallback as a } from "react";
|
|
4
4
|
//#region src/http/use-describe-api-error.ts
|
|
5
|
-
function
|
|
6
|
-
let
|
|
7
|
-
return i
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
function o(e, t, r) {
|
|
6
|
+
let i = e?.(t);
|
|
7
|
+
return i && i !== t ? i : n[r];
|
|
8
|
+
}
|
|
9
|
+
function s() {
|
|
10
|
+
let n = i()?.t;
|
|
11
|
+
return a((i, a) => r(i, a, {
|
|
12
|
+
offline: o(n, e, "offline"),
|
|
13
|
+
validation: o(n, t, "validation")
|
|
14
|
+
}), [n]);
|
|
11
15
|
}
|
|
12
16
|
//#endregion
|
|
13
|
-
export {
|
|
17
|
+
export { s as useDescribeApiError };
|
|
14
18
|
|
|
15
19
|
//# sourceMappingURL=use-describe-api-error.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-describe-api-error.js","names":[],"sources":["../../src/http/use-describe-api-error.ts"],"sourcesContent":["import { useCallback } from \"react\";\n\nimport { useOptionalI18n } from \"../i18n/I18nProvider\";\nimport {\n API_ERROR_OFFLINE_KEY,\n DEFAULT_API_ERROR_STRINGS,\n describeApiError,\n} from \"./describe-api-error\";\n\n/**\n * {@link describeApiError} with its fixed sentences resolved through the active\n * `I18nProvider`.\n *\n * The funnel is not duplicated — this hook only supplies the strings and calls\n * the pure function. Which is also why both exist: the pure one runs in an\n * interceptor or a logger, where there is no React tree to read a context from,\n * and this one runs in a component without every caller passing translations\n * down by hand.\n *\n * Works with no provider at all: i18n is opt-in in this SDK, so a missing\n * provider — or a catalog that never defined `tempest.error.offline` — falls\n * back to the pt-BR default rather than crashing or printing the raw key.\n *\n * @example\n * const describe = useDescribeApiError();\n * const { mutate } = useMutation({\n * mutationFn: save,\n * onError: (error) => toast(describe(error, t(\"orders.saveFailed\"))),\n * });\n *\n * @returns A stable `(error, fallback) => string` function.\n */\nexport function useDescribeApiError(): (error: unknown, fallback: string) => string {\n const i18n = useOptionalI18n();\n const translate = i18n?.t;\n\n return useCallback(\n (error: unknown, fallback: string) => {\n
|
|
1
|
+
{"version":3,"file":"use-describe-api-error.js","names":[],"sources":["../../src/http/use-describe-api-error.ts"],"sourcesContent":["import { useCallback } from \"react\";\n\nimport { useOptionalI18n } from \"../i18n/I18nProvider\";\nimport {\n API_ERROR_OFFLINE_KEY,\n API_ERROR_VALIDATION_KEY,\n DEFAULT_API_ERROR_STRINGS,\n describeApiError,\n} from \"./describe-api-error\";\n\n/**\n * {@link describeApiError} with its fixed sentences resolved through the active\n * `I18nProvider`.\n *\n * The funnel is not duplicated — this hook only supplies the strings and calls\n * the pure function. Which is also why both exist: the pure one runs in an\n * interceptor or a logger, where there is no React tree to read a context from,\n * and this one runs in a component without every caller passing translations\n * down by hand.\n *\n * Works with no provider at all: i18n is opt-in in this SDK, so a missing\n * provider — or a catalog that never defined `tempest.error.offline` — falls\n * back to the pt-BR default rather than crashing or printing the raw key.\n *\n * @example\n * const describe = useDescribeApiError();\n * const { mutate } = useMutation({\n * mutationFn: save,\n * onError: (error) => toast(describe(error, t(\"orders.saveFailed\"))),\n * });\n *\n * @returns A stable `(error, fallback) => string` function.\n */\n/**\n * Look one sentence up in the active catalog, falling back to the pt-BR default.\n *\n * `t` returns the key itself on a miss, so the identity check is what separates\n * \"the catalog answered\" from \"the catalog has no such key\" — printing\n * `tempest.error.validation` at a user is worse than printing pt-BR at them.\n *\n * @param translate - The active catalog's `t`, if any provider is mounted.\n * @param key - The translation key to look up.\n * @param fallbackKey - Which {@link DEFAULT_API_ERROR_STRINGS} entry to use on a miss.\n * @returns The sentence to hand to `describeApiError`.\n */\nfunction resolve(\n translate: ((key: string) => string) | undefined,\n key: string,\n fallbackKey: keyof typeof DEFAULT_API_ERROR_STRINGS,\n): string {\n const translated = translate?.(key);\n return translated && translated !== key ? translated : DEFAULT_API_ERROR_STRINGS[fallbackKey];\n}\n\nexport function useDescribeApiError(): (error: unknown, fallback: string) => string {\n const i18n = useOptionalI18n();\n const translate = i18n?.t;\n\n return useCallback(\n (error: unknown, fallback: string) => {\n return describeApiError(error, fallback, {\n offline: resolve(translate, API_ERROR_OFFLINE_KEY, \"offline\"),\n validation: resolve(translate, API_ERROR_VALIDATION_KEY, \"validation\"),\n });\n },\n [translate],\n );\n}\n"],"mappings":";;;;AA6CA,SAAS,EACL,GACA,GACA,GACM;CACN,IAAM,IAAa,IAAY,CAAG;CAClC,OAAO,KAAc,MAAe,IAAM,IAAa,EAA0B;AACrF;AAEA,SAAgB,IAAoE;CAEhF,IAAM,IADO,EACK,CAAA,EAAM;CAExB,OAAO,GACF,GAAgB,MACN,EAAiB,GAAO,GAAU;EACrC,SAAS,EAAQ,GAAW,GAAuB,SAAS;EAC5D,YAAY,EAAQ,GAAW,GAA0B,YAAY;CACzE,CAAC,GAEL,CAAC,CAAS,CACd;AACJ"}
|
package/dist/icons/Icon.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../utils/dev-mode.cjs"),t=require("./icon-context.cjs"),n=require("./shard-cache.cjs"),
|
|
1
|
+
const e=require("../utils/dev-mode.cjs"),t=require("./icon-context.cjs"),n=require("./normalize-icon-name.cjs"),r=require("./shard-cache.cjs"),i=require("./use-icon.cjs");let a=require("react");function o({name:o,icon:s,size:l,strokeWidth:u,fallback:d=null,normalize:f=!0,...p}){let m=t.useIconContext(),h=o===void 0?void 0:f?n.normalizeIconName(o):o,g=i.useIcon(h),_=s??g;return _?(0,a.createElement)(_,{size:l??m?.size,strokeWidth:u??m?.strokeWidth,...p}):(e.isDevBuild()&&o!==void 0&&h!==void 0&&r.iconStatus(h)===`missing`&&c(o),d)}var s=new Set;function c(e){s.has(e)||(s.add(e),console.warn(`[tempest-react-sdk] <Icon name="${e}" /> — no such lucide icon. Slugs are kebab-case ("circle-alert", not "CircleAlert"); check against \`iconNames\`.`))}exports.Icon=o;
|
|
2
2
|
//# sourceMappingURL=Icon.cjs.map
|
package/dist/icons/Icon.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.cjs","names":[],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { createElement, type ReactNode, type SVGProps } from \"react\";\n\nimport type { IconName } from \"./generated/icon-name\";\nimport { useIconContext } from \"./icon-context\";\nimport { iconStatus } from \"./shard-cache\";\nimport { useIcon } from \"./use-icon\";\nimport { isDevBuild } from \"../utils\";\n\
|
|
1
|
+
{"version":3,"file":"Icon.cjs","names":[],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { createElement, type ReactNode, type SVGProps } from \"react\";\nimport type { LucideIcon } from \"lucide-react\";\n\nimport type { IconName } from \"./generated/icon-name\";\nimport { useIconContext } from \"./icon-context\";\nimport { normalizeIconName } from \"./normalize-icon-name\";\nimport { iconStatus } from \"./shard-cache\";\nimport { useIcon } from \"./use-icon\";\nimport { isDevBuild } from \"../utils/dev-mode\";\n\ninterface IconBaseProps extends Omit<SVGProps<SVGSVGElement>, \"ref\" | \"name\"> {\n /** Width and height in px. Defaults to the provider's value, then lucide's `24`. */\n size?: number | string;\n /** Stroke width. Defaults to the provider's value, then lucide's `2`. */\n strokeWidth?: number;\n /**\n * Rendered while the icon's shard is in flight, and for a slug that does not\n * exist at all. Defaults to nothing.\n *\n * Pass a same-sized placeholder when the surrounding layout would otherwise\n * shift. Note that a slug already in the registry or the cache never renders\n * this — it resolves during render.\n */\n fallback?: ReactNode;\n /**\n * Clean up `name` before looking it up. Default `true`.\n *\n * A stored `icon_code` arrives dirty — `shopping_cart`, `\" Save\"`, a slug\n * lucide deprecated two releases ago — and normalizing is what makes those\n * render instead of falling back. `false` asks for a strict lookup, for the\n * case where you want an unexpected spelling to be visible rather than\n * quietly repaired.\n *\n * Ignored when the icon is passed as a component.\n */\n normalize?: boolean;\n}\n\n/**\n * Address the icon by slug — the reason this component exists.\n *\n * The slug is typed as the union of every name lucide ships, so a typo is a\n * compile error, while still accepting a plain `string` for the case that\n * motivates the whole module: a name arriving from an API, a CMS or a config\n * table.\n */\ninterface IconByNameProps extends IconBaseProps {\n name: IconName | (string & {});\n icon?: never;\n}\n\n/**\n * Address the icon by component, for a call site that already imported it.\n *\n * No lookup, no registry, no shard: the component is rendered as passed. It is\n * there so a screen mixing literal icons with data-driven ones can keep using one\n * component instead of alternating between `<Icon name>` and `<Wrench />`, which\n * is what makes the shared `size`/`strokeWidth` defaults apply to both.\n */\ninterface IconByComponentProps extends IconBaseProps {\n icon: LucideIcon;\n name?: never;\n}\n\nexport type IconProps = IconByNameProps | IconByComponentProps;\n\n/**\n * Render a lucide icon by slug.\n *\n * All ~2000 lucide icons are addressable, without the cost that makes\n * `lucide-react`'s own `DynamicIcon` unusable: its icon map holds a dynamic\n * `import()` per icon, so a bundler has to emit ~2000 chunk boundaries and the\n * browser floods with requests. Here a slug the app wrote as a literal is\n * resolved from a static registry, and a slug only known at runtime pulls a\n * single shard covering every icon sharing its initial letter.\n *\n * An unknown slug renders `fallback` (nothing, by default) and warns in dev only\n * — it never throws, because a bad name from an API must not take down the tree.\n *\n * `name` is normalized before the lookup, so a stored `icon_code` renders whether\n * it was written `shopping_cart`, `\" Save\"` or under a slug lucide has since\n * deprecated. Pass `normalize={false}` for a strict lookup.\n *\n * @example\n * <Icon name=\"save\" size={18} />\n * <Icon name={row.iconSlug} fallback={<span className=\"skeleton\" />} />\n * <Icon icon={Wrench} size={18} />\n */\nexport function Icon({\n name,\n icon,\n size,\n strokeWidth,\n fallback = null,\n normalize = true,\n ...rest\n}: IconProps): ReactNode {\n const context = useIconContext();\n const slug = name === undefined ? undefined : normalize ? normalizeIconName(name) : name;\n const fromSlug = useIcon(slug);\n const resolved = icon ?? fromSlug;\n\n if (!resolved) {\n if (isDevBuild() && name !== undefined && slug !== undefined) {\n if (iconStatus(slug) === \"missing\") warnUnknownIcon(name);\n }\n return fallback;\n }\n\n return createElement(resolved, {\n size: size ?? context?.size,\n strokeWidth: strokeWidth ?? context?.strokeWidth,\n ...rest,\n });\n}\n\nconst warnedSlugs = new Set<string>();\n\n/**\n * Warn once per unknown slug.\n *\n * Once, because `<Icon>` re-renders and a warning per render would bury the\n * console; the set is never cleared, since a slug that does not exist will not\n * start existing within the life of the page.\n *\n * Reports the name **as written**, not the normalized slug: the reader is the\n * developer who typed it, and `\"CircleAlert\"` is a far more useful thing to see in\n * the console than the `\"circlealert\"` it normalizes to.\n *\n * @param name - The slug that resolved to nothing, as passed.\n */\nfunction warnUnknownIcon(name: string): void {\n if (warnedSlugs.has(name)) return;\n warnedSlugs.add(name);\n console.warn(\n `[tempest-react-sdk] <Icon name=\"${name}\" /> — no such lucide icon. ` +\n `Slugs are kebab-case (\"circle-alert\", not \"CircleAlert\"); check against \\`iconNames\\`.`,\n );\n}\n"],"mappings":"kMAwFA,SAAgB,EAAK,CACjB,OACA,OACA,OACA,cACA,WAAW,KACX,YAAY,GACZ,GAAG,GACkB,CACrB,IAAM,EAAU,EAAA,eAAe,EACzB,EAAO,IAAS,IAAA,GAAY,IAAA,GAAY,EAAY,EAAA,kBAAkB,CAAI,EAAI,EAC9E,EAAW,EAAA,QAAQ,CAAI,EACvB,EAAW,GAAQ,EASzB,OAPK,GAOL,EAAO,EAAA,cAAA,CAAc,EAAU,CAC3B,KAAM,GAAQ,GAAS,KACvB,YAAa,GAAe,GAAS,YACrC,GAAG,CACP,CAAC,GAVO,EAAA,WAAW,GAAK,IAAS,IAAA,IAAa,IAAS,IAAA,IAC3C,EAAA,WAAW,CAAI,IAAM,WAAW,EAAgB,CAAI,EAErD,EAQf,CAEA,IAAM,EAAc,IAAI,IAexB,SAAS,EAAgB,EAAoB,CACrC,EAAY,IAAI,CAAI,IACxB,EAAY,IAAI,CAAI,EACpB,QAAQ,KACJ,mCAAmC,EAAK,mHAE5C,EACJ"}
|
package/dist/icons/Icon.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { isDevBuild as e } from "../utils/dev-mode.js";
|
|
2
2
|
import { useIconContext as t } from "./icon-context.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { normalizeIconName as n } from "./normalize-icon-name.js";
|
|
4
|
+
import { iconStatus as r } from "./shard-cache.js";
|
|
5
|
+
import { useIcon as i } from "./use-icon.js";
|
|
6
|
+
import { createElement as a } from "react";
|
|
6
7
|
//#region src/icons/Icon.tsx
|
|
7
|
-
function
|
|
8
|
-
let
|
|
9
|
-
return
|
|
10
|
-
size:
|
|
11
|
-
strokeWidth:
|
|
12
|
-
...
|
|
13
|
-
}) : (e() &&
|
|
8
|
+
function o({ name: o, icon: s, size: l, strokeWidth: u, fallback: d = null, normalize: f = !0, ...p }) {
|
|
9
|
+
let m = t(), h = o === void 0 ? void 0 : f ? n(o) : o, g = i(h), _ = s ?? g;
|
|
10
|
+
return _ ? a(_, {
|
|
11
|
+
size: l ?? m?.size,
|
|
12
|
+
strokeWidth: u ?? m?.strokeWidth,
|
|
13
|
+
...p
|
|
14
|
+
}) : (e() && o !== void 0 && h !== void 0 && r(h) === "missing" && c(o), d);
|
|
14
15
|
}
|
|
15
|
-
var
|
|
16
|
-
function
|
|
17
|
-
|
|
16
|
+
var s = /* @__PURE__ */ new Set();
|
|
17
|
+
function c(e) {
|
|
18
|
+
s.has(e) || (s.add(e), console.warn(`[tempest-react-sdk] <Icon name="${e}" /> — no such lucide icon. Slugs are kebab-case ("circle-alert", not "CircleAlert"); check against \`iconNames\`.`));
|
|
18
19
|
}
|
|
19
20
|
//#endregion
|
|
20
|
-
export {
|
|
21
|
+
export { o as Icon };
|
|
21
22
|
|
|
22
23
|
//# sourceMappingURL=Icon.js.map
|
package/dist/icons/Icon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.js","names":[],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { createElement, type ReactNode, type SVGProps } from \"react\";\n\nimport type { IconName } from \"./generated/icon-name\";\nimport { useIconContext } from \"./icon-context\";\nimport { iconStatus } from \"./shard-cache\";\nimport { useIcon } from \"./use-icon\";\nimport { isDevBuild } from \"../utils\";\n\
|
|
1
|
+
{"version":3,"file":"Icon.js","names":[],"sources":["../../src/icons/Icon.tsx"],"sourcesContent":["import { createElement, type ReactNode, type SVGProps } from \"react\";\nimport type { LucideIcon } from \"lucide-react\";\n\nimport type { IconName } from \"./generated/icon-name\";\nimport { useIconContext } from \"./icon-context\";\nimport { normalizeIconName } from \"./normalize-icon-name\";\nimport { iconStatus } from \"./shard-cache\";\nimport { useIcon } from \"./use-icon\";\nimport { isDevBuild } from \"../utils/dev-mode\";\n\ninterface IconBaseProps extends Omit<SVGProps<SVGSVGElement>, \"ref\" | \"name\"> {\n /** Width and height in px. Defaults to the provider's value, then lucide's `24`. */\n size?: number | string;\n /** Stroke width. Defaults to the provider's value, then lucide's `2`. */\n strokeWidth?: number;\n /**\n * Rendered while the icon's shard is in flight, and for a slug that does not\n * exist at all. Defaults to nothing.\n *\n * Pass a same-sized placeholder when the surrounding layout would otherwise\n * shift. Note that a slug already in the registry or the cache never renders\n * this — it resolves during render.\n */\n fallback?: ReactNode;\n /**\n * Clean up `name` before looking it up. Default `true`.\n *\n * A stored `icon_code` arrives dirty — `shopping_cart`, `\" Save\"`, a slug\n * lucide deprecated two releases ago — and normalizing is what makes those\n * render instead of falling back. `false` asks for a strict lookup, for the\n * case where you want an unexpected spelling to be visible rather than\n * quietly repaired.\n *\n * Ignored when the icon is passed as a component.\n */\n normalize?: boolean;\n}\n\n/**\n * Address the icon by slug — the reason this component exists.\n *\n * The slug is typed as the union of every name lucide ships, so a typo is a\n * compile error, while still accepting a plain `string` for the case that\n * motivates the whole module: a name arriving from an API, a CMS or a config\n * table.\n */\ninterface IconByNameProps extends IconBaseProps {\n name: IconName | (string & {});\n icon?: never;\n}\n\n/**\n * Address the icon by component, for a call site that already imported it.\n *\n * No lookup, no registry, no shard: the component is rendered as passed. It is\n * there so a screen mixing literal icons with data-driven ones can keep using one\n * component instead of alternating between `<Icon name>` and `<Wrench />`, which\n * is what makes the shared `size`/`strokeWidth` defaults apply to both.\n */\ninterface IconByComponentProps extends IconBaseProps {\n icon: LucideIcon;\n name?: never;\n}\n\nexport type IconProps = IconByNameProps | IconByComponentProps;\n\n/**\n * Render a lucide icon by slug.\n *\n * All ~2000 lucide icons are addressable, without the cost that makes\n * `lucide-react`'s own `DynamicIcon` unusable: its icon map holds a dynamic\n * `import()` per icon, so a bundler has to emit ~2000 chunk boundaries and the\n * browser floods with requests. Here a slug the app wrote as a literal is\n * resolved from a static registry, and a slug only known at runtime pulls a\n * single shard covering every icon sharing its initial letter.\n *\n * An unknown slug renders `fallback` (nothing, by default) and warns in dev only\n * — it never throws, because a bad name from an API must not take down the tree.\n *\n * `name` is normalized before the lookup, so a stored `icon_code` renders whether\n * it was written `shopping_cart`, `\" Save\"` or under a slug lucide has since\n * deprecated. Pass `normalize={false}` for a strict lookup.\n *\n * @example\n * <Icon name=\"save\" size={18} />\n * <Icon name={row.iconSlug} fallback={<span className=\"skeleton\" />} />\n * <Icon icon={Wrench} size={18} />\n */\nexport function Icon({\n name,\n icon,\n size,\n strokeWidth,\n fallback = null,\n normalize = true,\n ...rest\n}: IconProps): ReactNode {\n const context = useIconContext();\n const slug = name === undefined ? undefined : normalize ? normalizeIconName(name) : name;\n const fromSlug = useIcon(slug);\n const resolved = icon ?? fromSlug;\n\n if (!resolved) {\n if (isDevBuild() && name !== undefined && slug !== undefined) {\n if (iconStatus(slug) === \"missing\") warnUnknownIcon(name);\n }\n return fallback;\n }\n\n return createElement(resolved, {\n size: size ?? context?.size,\n strokeWidth: strokeWidth ?? context?.strokeWidth,\n ...rest,\n });\n}\n\nconst warnedSlugs = new Set<string>();\n\n/**\n * Warn once per unknown slug.\n *\n * Once, because `<Icon>` re-renders and a warning per render would bury the\n * console; the set is never cleared, since a slug that does not exist will not\n * start existing within the life of the page.\n *\n * Reports the name **as written**, not the normalized slug: the reader is the\n * developer who typed it, and `\"CircleAlert\"` is a far more useful thing to see in\n * the console than the `\"circlealert\"` it normalizes to.\n *\n * @param name - The slug that resolved to nothing, as passed.\n */\nfunction warnUnknownIcon(name: string): void {\n if (warnedSlugs.has(name)) return;\n warnedSlugs.add(name);\n console.warn(\n `[tempest-react-sdk] <Icon name=\"${name}\" /> — no such lucide icon. ` +\n `Slugs are kebab-case (\"circle-alert\", not \"CircleAlert\"); check against \\`iconNames\\`.`,\n );\n}\n"],"mappings":";;;;;;;AAwFA,SAAgB,EAAK,EACjB,SACA,SACA,SACA,gBACA,cAAW,MACX,eAAY,IACZ,GAAG,KACkB;CACrB,IAAM,IAAU,EAAe,GACzB,IAAO,MAAS,KAAA,IAAY,KAAA,IAAY,IAAY,EAAkB,CAAI,IAAI,GAC9E,IAAW,EAAQ,CAAI,GACvB,IAAW,KAAQ;CASzB,OAPK,IAOE,EAAc,GAAU;EAC3B,MAAM,KAAQ,GAAS;EACvB,aAAa,KAAe,GAAS;EACrC,GAAG;CACP,CAAC,KAVO,EAAW,KAAK,MAAS,KAAA,KAAa,MAAS,KAAA,KAC3C,EAAW,CAAI,MAAM,aAAW,EAAgB,CAAI,GAErD;AAQf;AAEA,IAAM,oBAAc,IAAI,IAAY;AAepC,SAAS,EAAgB,GAAoB;CACrC,EAAY,IAAI,CAAI,MACxB,EAAY,IAAI,CAAI,GACpB,QAAQ,KACJ,mCAAmC,EAAK,mHAE5C;AACJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../utils/cn.cjs"),t=require("./generated/icon-names.cjs"),n=require("./normalize-icon-name.cjs"),r=require("./Icon.cjs"),i=require("./validate-icon-name.cjs"),a=require("./IconPicker.module.cjs");let o=require("react"),s=require("react/jsx-runtime");function c({value:c,onChange:l,limit:u=40,previewSize:d=20,invalidMessage:f,emptyPreview:p=null,className:m,...h}){let g=(0,o.useId)(),_=(0,o.useRef)(null),v=i.validateIconName(c,f),y=(0,o.useMemo)(()=>{let e=n.normalizeIconName(c);return(e===``?t.iconNames:t.iconNames.filter(t=>t.includes(e))).slice(0,u)},[c,u]);return(0,o.useEffect)(()=>{_.current?.setCustomValidity(v??``)},[v]),(0,s.jsxs)(`span`,{className:e.cn(a.default.picker,m),children:[(0,s.jsx)(`span`,{className:a.default.preview,"aria-hidden":`true`,children:v===void 0&&c.trim()!==``?(0,s.jsx)(r.Icon,{name:c,size:d,fallback:p}):p}),(0,s.jsx)(`input`,{...h,ref:_,type:`text`,className:a.default.input,list:g,value:c,"aria-invalid":v!==void 0||void 0,onChange:e=>l(n.normalizeIconName(e.target.value))}),(0,s.jsx)(`datalist`,{id:g,children:y.map(e=>(0,s.jsx)(`option`,{value:e},e))})]})}exports.IconPicker=c;
|
|
2
|
+
//# sourceMappingURL=IconPicker.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconPicker.cjs","names":[],"sources":["../../src/icons/IconPicker.tsx"],"sourcesContent":["import { useEffect, useId, useMemo, useRef, type InputHTMLAttributes, type ReactNode } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { iconNames } from \"./generated/icon-names\";\nimport { Icon } from \"./Icon\";\nimport { normalizeIconName } from \"./normalize-icon-name\";\nimport { validateIconName } from \"./validate-icon-name\";\nimport styles from \"./IconPicker.module.css\";\n\n/**\n * @tempest-limits props-count — value/onChange are the field, limit/placeholder\n * the suggestion list, and previewSize/invalidMessage the two things a form\n * around it needs to restyle or translate.\n */\nexport interface IconPickerProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"onChange\" | \"list\" | \"type\"\n> {\n /** The chosen slug. Always canonical — see `onChange`. */\n value: string;\n /**\n * Fires with the **canonical** slug on every keystroke.\n *\n * Legacy spellings are normalized on the way out (`Shopping_Cart` →\n * `shopping-cart`, `alert-circle` → `circle-alert`), so what a form stores is\n * what `<Icon>` resolves without further cleanup.\n */\n onChange: (slug: string) => void;\n /**\n * How many suggestions to render. Default `40`.\n *\n * There are 2024 slugs, and building every one as an `<option>` on each\n * keystroke freezes the datalist — which is the reason this prop exists rather\n * than a \"show everything\" default.\n */\n limit?: number;\n /** Size of the preview glyph, in px. Default `20`. */\n previewSize?: number;\n /** Overrides the message shown for a slug that does not exist. */\n invalidMessage?: string;\n /** Rendered in the preview box while nothing valid is chosen. */\n emptyPreview?: ReactNode;\n}\n\n/**\n * An icon field: native autocomplete over every lucide slug, plus a preview.\n *\n * Every panel that lets someone choose an icon was rewriting this — filter the\n * list, cap the suggestions, build the `<datalist>`, and block submit when the\n * typed name does not exist. That last step is the one that matters: without it\n * an invalid value reaches the database and only shows up later as a missing icon\n * on every screen that renders the record.\n *\n * Validation is wired to the **native** form: the input carries a custom validity\n * message, so a plain `<form>` refuses to submit and the browser points at the\n * field. `validateIconName` is exported for react-hook-form and zod.\n *\n * Built on `<datalist>` rather than a custom listbox on purpose: keyboard,\n * screen-reader and mobile behaviour come from the platform, and the component\n * stays small enough that its cost is the slug list it has to import — ~7 KB\n * brotli, which only a picker pays.\n *\n * @example\n * const [icon, setIcon] = useState(\"\");\n *\n * <form onSubmit={save}>\n * <IconPicker value={icon} onChange={setIcon} required />\n * <button type=\"submit\">Salvar</button>\n * </form>\n */\nexport function IconPicker({\n value,\n onChange,\n limit = 40,\n previewSize = 20,\n invalidMessage,\n emptyPreview = null,\n className,\n ...rest\n}: IconPickerProps): ReactNode {\n const listId = useId();\n const input = useRef<HTMLInputElement>(null);\n const error = validateIconName(value, invalidMessage);\n\n const suggestions = useMemo(() => {\n const query = normalizeIconName(value);\n const matches = query === \"\" ? iconNames : iconNames.filter((name) => name.includes(query));\n return matches.slice(0, limit);\n }, [value, limit]);\n\n useEffect(() => {\n input.current?.setCustomValidity(error ?? \"\");\n }, [error]);\n\n return (\n <span className={cn(styles.picker, className)}>\n <span className={styles.preview} aria-hidden=\"true\">\n {error === undefined && value.trim() !== \"\" ? (\n <Icon name={value} size={previewSize} fallback={emptyPreview} />\n ) : (\n emptyPreview\n )}\n </span>\n <input\n {...rest}\n ref={input}\n type=\"text\"\n className={styles.input}\n list={listId}\n value={value}\n aria-invalid={error !== undefined || undefined}\n onChange={(event) => onChange(normalizeIconName(event.target.value))}\n />\n <datalist id={listId}>\n {suggestions.map((name) => (\n <option key={name} value={name} />\n ))}\n </datalist>\n </span>\n );\n}\n"],"mappings":"2QAsEA,SAAgB,EAAW,CACvB,QACA,WACA,QAAQ,GACR,cAAc,GACd,iBACA,eAAe,KACf,YACA,GAAG,GACwB,CAC3B,IAAM,GAAA,EAAS,EAAA,MAAA,CAAM,EACf,GAAA,EAAQ,EAAA,OAAA,CAAyB,IAAI,EACrC,EAAQ,EAAA,iBAAiB,EAAO,CAAc,EAE9C,GAAA,EAAc,EAAA,QAAA,KAAc,CAC9B,IAAM,EAAQ,EAAA,kBAAkB,CAAK,EAErC,OADgB,IAAU,GAAK,EAAA,UAAY,EAAA,UAAU,OAAQ,GAAS,EAAK,SAAS,CAAK,CAAC,EAAA,CAC3E,MAAM,EAAG,CAAK,CACjC,EAAG,CAAC,EAAO,CAAK,CAAC,EAMjB,OAJA,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAM,SAAS,kBAAkB,GAAS,EAAE,CAChD,EAAG,CAAC,CAAK,CAAC,GAGN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,OAAQ,CAAS,EAA5C,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,QAAS,cAAY,OACxC,SAAA,IAAU,IAAA,IAAa,EAAM,KAAK,IAAM,IACrC,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAO,KAAM,EAAa,SAAU,CAAe,CAAA,EAE/D,CAEF,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,GAAI,EACJ,IAAK,EACL,KAAK,OACL,UAAW,EAAA,QAAO,MAClB,KAAM,EACC,QACP,eAAc,IAAU,IAAA,IAAa,IAAA,GACrC,SAAW,GAAU,EAAS,EAAA,kBAAkB,EAAM,OAAO,KAAK,CAAC,CACtE,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,WAAD,CAAU,GAAI,EACT,SAAA,EAAY,IAAK,IACd,EAAA,EAAA,IAAA,CAAC,SAAD,CAAmB,MAAO,CAAO,EAApB,CAAoB,CACpC,CACK,CAAA,CACR,GAEd"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { cn as e } from "../utils/cn.js";
|
|
2
|
+
import { iconNames as t } from "./generated/icon-names.js";
|
|
3
|
+
import { normalizeIconName as n } from "./normalize-icon-name.js";
|
|
4
|
+
import { Icon as r } from "./Icon.js";
|
|
5
|
+
import { validateIconName as i } from "./validate-icon-name.js";
|
|
6
|
+
import a from "./IconPicker.module.js";
|
|
7
|
+
import { useEffect as o, useId as s, useMemo as c, useRef as l } from "react";
|
|
8
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
9
|
+
//#region src/icons/IconPicker.tsx
|
|
10
|
+
function f({ value: f, onChange: p, limit: m = 40, previewSize: h = 20, invalidMessage: g, emptyPreview: _ = null, className: v, ...y }) {
|
|
11
|
+
let b = s(), x = l(null), S = i(f, g), C = c(() => {
|
|
12
|
+
let e = n(f);
|
|
13
|
+
return (e === "" ? t : t.filter((t) => t.includes(e))).slice(0, m);
|
|
14
|
+
}, [f, m]);
|
|
15
|
+
return o(() => {
|
|
16
|
+
x.current?.setCustomValidity(S ?? "");
|
|
17
|
+
}, [S]), /* @__PURE__ */ d("span", {
|
|
18
|
+
className: e(a.picker, v),
|
|
19
|
+
children: [
|
|
20
|
+
/* @__PURE__ */ u("span", {
|
|
21
|
+
className: a.preview,
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
children: S === void 0 && f.trim() !== "" ? /* @__PURE__ */ u(r, {
|
|
24
|
+
name: f,
|
|
25
|
+
size: h,
|
|
26
|
+
fallback: _
|
|
27
|
+
}) : _
|
|
28
|
+
}),
|
|
29
|
+
/* @__PURE__ */ u("input", {
|
|
30
|
+
...y,
|
|
31
|
+
ref: x,
|
|
32
|
+
type: "text",
|
|
33
|
+
className: a.input,
|
|
34
|
+
list: b,
|
|
35
|
+
value: f,
|
|
36
|
+
"aria-invalid": S !== void 0 || void 0,
|
|
37
|
+
onChange: (e) => p(n(e.target.value))
|
|
38
|
+
}),
|
|
39
|
+
/* @__PURE__ */ u("datalist", {
|
|
40
|
+
id: b,
|
|
41
|
+
children: C.map((e) => /* @__PURE__ */ u("option", { value: e }, e))
|
|
42
|
+
})
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { f as IconPicker };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=IconPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconPicker.js","names":[],"sources":["../../src/icons/IconPicker.tsx"],"sourcesContent":["import { useEffect, useId, useMemo, useRef, type InputHTMLAttributes, type ReactNode } from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { iconNames } from \"./generated/icon-names\";\nimport { Icon } from \"./Icon\";\nimport { normalizeIconName } from \"./normalize-icon-name\";\nimport { validateIconName } from \"./validate-icon-name\";\nimport styles from \"./IconPicker.module.css\";\n\n/**\n * @tempest-limits props-count — value/onChange are the field, limit/placeholder\n * the suggestion list, and previewSize/invalidMessage the two things a form\n * around it needs to restyle or translate.\n */\nexport interface IconPickerProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"onChange\" | \"list\" | \"type\"\n> {\n /** The chosen slug. Always canonical — see `onChange`. */\n value: string;\n /**\n * Fires with the **canonical** slug on every keystroke.\n *\n * Legacy spellings are normalized on the way out (`Shopping_Cart` →\n * `shopping-cart`, `alert-circle` → `circle-alert`), so what a form stores is\n * what `<Icon>` resolves without further cleanup.\n */\n onChange: (slug: string) => void;\n /**\n * How many suggestions to render. Default `40`.\n *\n * There are 2024 slugs, and building every one as an `<option>` on each\n * keystroke freezes the datalist — which is the reason this prop exists rather\n * than a \"show everything\" default.\n */\n limit?: number;\n /** Size of the preview glyph, in px. Default `20`. */\n previewSize?: number;\n /** Overrides the message shown for a slug that does not exist. */\n invalidMessage?: string;\n /** Rendered in the preview box while nothing valid is chosen. */\n emptyPreview?: ReactNode;\n}\n\n/**\n * An icon field: native autocomplete over every lucide slug, plus a preview.\n *\n * Every panel that lets someone choose an icon was rewriting this — filter the\n * list, cap the suggestions, build the `<datalist>`, and block submit when the\n * typed name does not exist. That last step is the one that matters: without it\n * an invalid value reaches the database and only shows up later as a missing icon\n * on every screen that renders the record.\n *\n * Validation is wired to the **native** form: the input carries a custom validity\n * message, so a plain `<form>` refuses to submit and the browser points at the\n * field. `validateIconName` is exported for react-hook-form and zod.\n *\n * Built on `<datalist>` rather than a custom listbox on purpose: keyboard,\n * screen-reader and mobile behaviour come from the platform, and the component\n * stays small enough that its cost is the slug list it has to import — ~7 KB\n * brotli, which only a picker pays.\n *\n * @example\n * const [icon, setIcon] = useState(\"\");\n *\n * <form onSubmit={save}>\n * <IconPicker value={icon} onChange={setIcon} required />\n * <button type=\"submit\">Salvar</button>\n * </form>\n */\nexport function IconPicker({\n value,\n onChange,\n limit = 40,\n previewSize = 20,\n invalidMessage,\n emptyPreview = null,\n className,\n ...rest\n}: IconPickerProps): ReactNode {\n const listId = useId();\n const input = useRef<HTMLInputElement>(null);\n const error = validateIconName(value, invalidMessage);\n\n const suggestions = useMemo(() => {\n const query = normalizeIconName(value);\n const matches = query === \"\" ? iconNames : iconNames.filter((name) => name.includes(query));\n return matches.slice(0, limit);\n }, [value, limit]);\n\n useEffect(() => {\n input.current?.setCustomValidity(error ?? \"\");\n }, [error]);\n\n return (\n <span className={cn(styles.picker, className)}>\n <span className={styles.preview} aria-hidden=\"true\">\n {error === undefined && value.trim() !== \"\" ? (\n <Icon name={value} size={previewSize} fallback={emptyPreview} />\n ) : (\n emptyPreview\n )}\n </span>\n <input\n {...rest}\n ref={input}\n type=\"text\"\n className={styles.input}\n list={listId}\n value={value}\n aria-invalid={error !== undefined || undefined}\n onChange={(event) => onChange(normalizeIconName(event.target.value))}\n />\n <datalist id={listId}>\n {suggestions.map((name) => (\n <option key={name} value={name} />\n ))}\n </datalist>\n </span>\n );\n}\n"],"mappings":";;;;;;;;;AAsEA,SAAgB,EAAW,EACvB,UACA,aACA,WAAQ,IACR,iBAAc,IACd,mBACA,kBAAe,MACf,cACA,GAAG,KACwB;CAC3B,IAAM,IAAS,EAAM,GACf,IAAQ,EAAyB,IAAI,GACrC,IAAQ,EAAiB,GAAO,CAAc,GAE9C,IAAc,QAAc;EAC9B,IAAM,IAAQ,EAAkB,CAAK;EAErC,QADgB,MAAU,KAAK,IAAY,EAAU,QAAQ,MAAS,EAAK,SAAS,CAAK,CAAC,EAAA,CAC3E,MAAM,GAAG,CAAK;CACjC,GAAG,CAAC,GAAO,CAAK,CAAC;CAMjB,OAJA,QAAgB;EACZ,EAAM,SAAS,kBAAkB,KAAS,EAAE;CAChD,GAAG,CAAC,CAAK,CAAC,GAGN,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,QAAQ,CAAS;EAA5C,UAAA;GACI,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAS,eAAY;IACxC,UAAA,MAAU,KAAA,KAAa,EAAM,KAAK,MAAM,KACrC,kBAAC,GAAD;KAAM,MAAM;KAAO,MAAM;KAAa,UAAU;IAAe,CAAA,IAE/D;GAEF,CAAA;GACN,kBAAC,SAAD;IACI,GAAI;IACJ,KAAK;IACL,MAAK;IACL,WAAW,EAAO;IAClB,MAAM;IACC;IACP,gBAAc,MAAU,KAAA,KAAa,KAAA;IACrC,WAAW,MAAU,EAAS,EAAkB,EAAM,OAAO,KAAK,CAAC;GACtE,CAAA;GACD,kBAAC,YAAD;IAAU,IAAI;IACT,UAAA,EAAY,KAAK,MACd,kBAAC,UAAD,EAAmB,OAAO,EAAO,GAApB,CAAoB,CACpC;GACK,CAAA;EACR;;AAEd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconPicker.module.cjs","names":[],"sources":["../../src/icons/IconPicker.module.css"],"sourcesContent":[".picker {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.preview {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 34px;\n height: 34px;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.input {\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: var(--tempest-text-sm);\n min-height: 34px;\n}\n\n.input:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 1px;\n}\n\n.input[aria-invalid=\"true\"] {\n border-color: var(--tempest-danger);\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/icons/IconPicker.module.css
|
|
2
|
+
var e = "tempest_picker_TP94V", t = "tempest_preview_lo-Gg", n = "tempest_input_5dPK-", r = {
|
|
3
|
+
picker: e,
|
|
4
|
+
preview: t,
|
|
5
|
+
input: n
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { r as default, n as input, e as picker, t as preview };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=IconPicker.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IconPicker.module.js","names":[],"sources":["../../src/icons/IconPicker.module.css"],"sourcesContent":[".picker {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.preview {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 34px;\n height: 34px;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.input {\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: var(--tempest-text-sm);\n min-height: 34px;\n}\n\n.input:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 1px;\n}\n\n.input[aria-invalid=\"true\"] {\n border-color: var(--tempest-danger);\n}\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alias.cjs","names":[],"sources":["../../src/icons/alias.ts"],"sourcesContent":["import { iconAliases } from \"./generated/aliases\";\n\n/**\n * Map a slug to the canonical slug that owns the icon.\n *\n * Lucide keeps 257 deprecated aliases (`alert-circle` → `circle-alert`), and a\n * slug persisted in a database years ago is exactly the case this feature exists\n * for, so an alias must keep resolving after a lucide bump renames it. Resolution\n * happens before the shard lookup, since only canonical slugs are sharded.\n *\n * Its own module, not part of `shard-cache`: everything that merely *names* an\n * icon needs this — `normalizeIconName`, `validateIconName`, a form checking a\n * value before submit — and none of that needs the shard loader index. Sharing a\n * module made a validator that never renders anything drag in all 45 shard\n * modules.\n *\n * @param slug - Any icon slug, canonical or deprecated.\n * @returns The canonical slug.\n */\nexport function resolveIconAlias(slug: string): string {\n return iconAliases[slug] ?? slug;\n}\n"],"mappings":"2CAmBA,SAAgB,EAAiB,EAAsB,CACnD,OAAO,EAAA,YAAY,IAAS,CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alias.js","names":[],"sources":["../../src/icons/alias.ts"],"sourcesContent":["import { iconAliases } from \"./generated/aliases\";\n\n/**\n * Map a slug to the canonical slug that owns the icon.\n *\n * Lucide keeps 257 deprecated aliases (`alert-circle` → `circle-alert`), and a\n * slug persisted in a database years ago is exactly the case this feature exists\n * for, so an alias must keep resolving after a lucide bump renames it. Resolution\n * happens before the shard lookup, since only canonical slugs are sharded.\n *\n * Its own module, not part of `shard-cache`: everything that merely *names* an\n * icon needs this — `normalizeIconName`, `validateIconName`, a form checking a\n * value before submit — and none of that needs the shard loader index. Sharing a\n * module made a validator that never renders anything drag in all 45 shard\n * modules.\n *\n * @param slug - Any icon slug, canonical or deprecated.\n * @returns The canonical slug.\n */\nexport function resolveIconAlias(slug: string): string {\n return iconAliases[slug] ?? slug;\n}\n"],"mappings":";;AAmBA,SAAgB,EAAiB,GAAsB;CACnD,OAAO,EAAY,MAAS;AAChC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={a:()=>Promise.resolve().then(()=>require("./shard-
|
|
1
|
+
var e=[{id:`shard-00`,from:`a-arrow-down`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-00.cjs"))},{id:`shard-01`,from:`amphora`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-01.cjs"))},{id:`shard-02`,from:`arrow-right-left`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-02.cjs"))},{id:`shard-03`,from:`badge-pound-sterling`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-03.cjs"))},{id:`shard-04`,from:`bell-electric`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-04.cjs"))},{id:`shard-05`,from:`book-image`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-05.cjs"))},{id:`shard-06`,from:`briefcase-conveyor-belt`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-06.cjs"))},{id:`shard-07`,from:`calendar-x`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-07.cjs"))},{id:`shard-08`,from:`chart-line`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-08.cjs"))},{id:`shard-09`,from:`circle-alert`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-09.cjs"))},{id:`shard-10`,from:`circle-small`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-10.cjs"))},{id:`shard-11`,from:`clock-fading`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-11.cjs"))},{id:`shard-12`,from:`concierge-bell`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-12.cjs"))},{id:`shard-13`,from:`database-arrow-up`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-13.cjs"))},{id:`shard-14`,from:`download`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-14.cjs"))},{id:`shard-15`,from:`face-slightly-frowning`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-15.cjs"))},{id:`shard-16`,from:`file-pen`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-16.cjs"))},{id:`shard-17`,from:`flashlight-off`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-17.cjs"))},{id:`shard-18`,from:`folder-up`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-18.cjs"))},{id:`shard-19`,from:`git-pull-request-closed`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-19.cjs"))},{id:`shard-20`,from:`hard-drive-download`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-20.cjs"))},{id:`shard-21`,from:`ice-cream-bowl`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-21.cjs"))},{id:`shard-22`,from:`languages`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-22.cjs"))},{id:`shard-23`,from:`list-checks`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-23.cjs"))},{id:`shard-24`,from:`mail-minus`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-24.cjs"))},{id:`shard-25`,from:`message-circle-dashed`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-25.cjs"))},{id:`shard-26`,from:`minimize-2`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-26.cjs"))},{id:`shard-27`,from:`move-horizontal`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-27.cjs"))},{id:`shard-28`,from:`package-open`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-28.cjs"))},{id:`shard-29`,from:`pen`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-29.cjs"))},{id:`shard-30`,from:`play-off`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-30.cjs"))},{id:`shard-31`,from:`receipt-japanese-yen`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-31.cjs"))},{id:`shard-32`,from:`rotate-ccw-key`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-32.cjs"))},{id:`shard-33`,from:`scan-text`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-33.cjs"))},{id:`shard-34`,from:`shield-ellipsis`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-34.cjs"))},{id:`shard-35`,from:`smartphone`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-35.cjs"))},{id:`shard-36`,from:`square-arrow-up-right`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-36.cjs"))},{id:`shard-37`,from:`square-power`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-37.cjs"))},{id:`shard-38`,from:`sticky-note-x`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-38.cjs"))},{id:`shard-39`,from:`tally-3`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-39.cjs"))},{id:`shard-40`,from:`timer-reset`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-40.cjs"))},{id:`shard-41`,from:`tv-minimal`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-41.cjs"))},{id:`shard-42`,from:`user-x`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-42.cjs"))},{id:`shard-43`,from:`waves-ladder`,size:40,load:()=>Promise.resolve().then(()=>require("./shard-43.cjs"))},{id:`shard-44`,from:`zodiac-pisces`,size:7,load:()=>Promise.resolve().then(()=>require("./shard-44.cjs"))}];exports.iconShards=e;
|
|
2
2
|
//# sourceMappingURL=loaders.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaders.cjs","names":[],"sources":["../../../src/icons/generated/loaders.ts"],"sourcesContent":["// GENERATED by scripts/gen-icons.mjs — do not edit.\n// Run `npm run gen:icons` after bumping lucide-react.\n\nimport type { LucideIcon } from \"lucide-react\";\n\n
|
|
1
|
+
{"version":3,"file":"loaders.cjs","names":[],"sources":["../../../src/icons/generated/loaders.ts"],"sourcesContent":["// GENERATED by scripts/gen-icons.mjs — do not edit.\n// Run `npm run gen:icons` after bumping lucide-react.\n\nimport type { LucideIcon } from \"lucide-react\";\n\n/** One lazily fetched range of icons. */\nexport interface IconShard {\n /** The chunk's module id — what shows up in a bundle and in a 404. */\n id: string;\n /** First slug in the range, in sort order. Its lower bound. */\n from: string;\n /** How many icons the range holds. */\n size: number;\n /** The dynamic import for the chunk. */\n load: () => Promise<{ default: Record<string, LucideIcon> }>;\n}\n\n/**\n * Every shard, in slug order.\n *\n * These are the only references to the shard modules, which is what keeps them\n * out of whatever chunk imports `Icon`: a bundler that sees no static edge to a\n * shard emits it as an async chunk fetched on first use.\n *\n * Sorted by `from`, so the owning shard for a slug is a binary search over this\n * array — 45 comparisons' worth of index instead of the 2000-entry\n * slug→chunk map that makes lucide's own `dynamicIconImports` cost 120 KB in the\n * main chunk.\n */\nexport const iconShards: readonly IconShard[] = [\n { id: \"shard-00\", from: \"a-arrow-down\", size: 40, load: () => import(\"./shard-00\") },\n { id: \"shard-01\", from: \"amphora\", size: 40, load: () => import(\"./shard-01\") },\n { id: \"shard-02\", from: \"arrow-right-left\", size: 40, load: () => import(\"./shard-02\") },\n { id: \"shard-03\", from: \"badge-pound-sterling\", size: 40, load: () => import(\"./shard-03\") },\n { id: \"shard-04\", from: \"bell-electric\", size: 40, load: () => import(\"./shard-04\") },\n { id: \"shard-05\", from: \"book-image\", size: 40, load: () => import(\"./shard-05\") },\n { id: \"shard-06\", from: \"briefcase-conveyor-belt\", size: 40, load: () => import(\"./shard-06\") },\n { id: \"shard-07\", from: \"calendar-x\", size: 40, load: () => import(\"./shard-07\") },\n { id: \"shard-08\", from: \"chart-line\", size: 40, load: () => import(\"./shard-08\") },\n { id: \"shard-09\", from: \"circle-alert\", size: 40, load: () => import(\"./shard-09\") },\n { id: \"shard-10\", from: \"circle-small\", size: 40, load: () => import(\"./shard-10\") },\n { id: \"shard-11\", from: \"clock-fading\", size: 40, load: () => import(\"./shard-11\") },\n { id: \"shard-12\", from: \"concierge-bell\", size: 40, load: () => import(\"./shard-12\") },\n { id: \"shard-13\", from: \"database-arrow-up\", size: 40, load: () => import(\"./shard-13\") },\n { id: \"shard-14\", from: \"download\", size: 40, load: () => import(\"./shard-14\") },\n { id: \"shard-15\", from: \"face-slightly-frowning\", size: 40, load: () => import(\"./shard-15\") },\n { id: \"shard-16\", from: \"file-pen\", size: 40, load: () => import(\"./shard-16\") },\n { id: \"shard-17\", from: \"flashlight-off\", size: 40, load: () => import(\"./shard-17\") },\n { id: \"shard-18\", from: \"folder-up\", size: 40, load: () => import(\"./shard-18\") },\n { id: \"shard-19\", from: \"git-pull-request-closed\", size: 40, load: () => import(\"./shard-19\") },\n { id: \"shard-20\", from: \"hard-drive-download\", size: 40, load: () => import(\"./shard-20\") },\n { id: \"shard-21\", from: \"ice-cream-bowl\", size: 40, load: () => import(\"./shard-21\") },\n { id: \"shard-22\", from: \"languages\", size: 40, load: () => import(\"./shard-22\") },\n { id: \"shard-23\", from: \"list-checks\", size: 40, load: () => import(\"./shard-23\") },\n { id: \"shard-24\", from: \"mail-minus\", size: 40, load: () => import(\"./shard-24\") },\n { id: \"shard-25\", from: \"message-circle-dashed\", size: 40, load: () => import(\"./shard-25\") },\n { id: \"shard-26\", from: \"minimize-2\", size: 40, load: () => import(\"./shard-26\") },\n { id: \"shard-27\", from: \"move-horizontal\", size: 40, load: () => import(\"./shard-27\") },\n { id: \"shard-28\", from: \"package-open\", size: 40, load: () => import(\"./shard-28\") },\n { id: \"shard-29\", from: \"pen\", size: 40, load: () => import(\"./shard-29\") },\n { id: \"shard-30\", from: \"play-off\", size: 40, load: () => import(\"./shard-30\") },\n { id: \"shard-31\", from: \"receipt-japanese-yen\", size: 40, load: () => import(\"./shard-31\") },\n { id: \"shard-32\", from: \"rotate-ccw-key\", size: 40, load: () => import(\"./shard-32\") },\n { id: \"shard-33\", from: \"scan-text\", size: 40, load: () => import(\"./shard-33\") },\n { id: \"shard-34\", from: \"shield-ellipsis\", size: 40, load: () => import(\"./shard-34\") },\n { id: \"shard-35\", from: \"smartphone\", size: 40, load: () => import(\"./shard-35\") },\n { id: \"shard-36\", from: \"square-arrow-up-right\", size: 40, load: () => import(\"./shard-36\") },\n { id: \"shard-37\", from: \"square-power\", size: 40, load: () => import(\"./shard-37\") },\n { id: \"shard-38\", from: \"sticky-note-x\", size: 40, load: () => import(\"./shard-38\") },\n { id: \"shard-39\", from: \"tally-3\", size: 40, load: () => import(\"./shard-39\") },\n { id: \"shard-40\", from: \"timer-reset\", size: 40, load: () => import(\"./shard-40\") },\n { id: \"shard-41\", from: \"tv-minimal\", size: 40, load: () => import(\"./shard-41\") },\n { id: \"shard-42\", from: \"user-x\", size: 40, load: () => import(\"./shard-42\") },\n { id: \"shard-43\", from: \"waves-ladder\", size: 40, load: () => import(\"./shard-43\") },\n { id: \"shard-44\", from: \"zodiac-pisces\", size: 7, load: () => import(\"./shard-44\") },\n];\n"],"mappings":"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"}
|