@protobase/ui 0.15.4 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/account/two-factor-setup.js +6 -5
  2. package/dist/app/app.js +2 -1
  3. package/dist/app/create/create-page.js +1 -0
  4. package/dist/app/create/create-record-form.js +2 -1
  5. package/dist/app/displays/custom-display.js +1 -1
  6. package/dist/app/displays/map-display.js +50 -34
  7. package/dist/app/displays/map-groups.js +12 -3
  8. package/dist/app/displays/measured-heights.js +23 -0
  9. package/dist/app/displays/record-card.js +2 -2
  10. package/dist/app/displays/virtual-cards.js +12 -14
  11. package/dist/app/field-editor.js +9 -1
  12. package/dist/app/index.html +2 -2
  13. package/dist/app/list-page.js +2 -2
  14. package/dist/app/map/approximate-position.js +76 -0
  15. package/dist/app/map/area-features.js +80 -0
  16. package/dist/app/map/maplibre.js +11 -0
  17. package/dist/app/map/position-areas.js +78 -0
  18. package/dist/app/map/record-map.js +2 -7
  19. package/dist/app/map/record-position.js +5 -4
  20. package/dist/app/map/records-map.js +24 -7
  21. package/dist/app/map/theme-color.js +23 -0
  22. package/dist/app/meta-gate.js +1 -1
  23. package/dist/app/nav-recent.js +1 -1
  24. package/dist/app/pages/blocks/card-frame.js +2 -2
  25. package/dist/app/pages/blocks/grid.js +10 -2
  26. package/dist/app/pages/blocks/link.js +1 -1
  27. package/dist/app/pages/blocks/page-block.js +1 -1
  28. package/dist/app/pages/blocks/stat.js +9 -5
  29. package/dist/app/pages/field-value.js +1 -1
  30. package/dist/app/record-page.js +8 -4
  31. package/dist/app/router.js +7 -8
  32. package/dist/app/saved/saved-records.js +1 -1
  33. package/dist/app/search/search-model.js +1 -1
  34. package/dist/app/searches/use-save-search.js +4 -3
  35. package/dist/app/source-notice.js +2 -2
  36. package/dist/app/use-record-editor.js +5 -3
  37. package/dist/app-shell/app-shell.d.ts +1 -0
  38. package/dist/app-shell/app-shell.js +6 -4
  39. package/dist/app-shell/page-scroll.js +21 -4
  40. package/dist/app-shell/sidebar.d.ts +1 -0
  41. package/dist/app-shell/sidebar.js +4 -4
  42. package/dist/app-shell/top-bar.js +4 -4
  43. package/dist/auth/auth-gate.js +18 -9
  44. package/dist/auth/auth-provider.js +1 -0
  45. package/dist/auth/code-form.js +77 -0
  46. package/dist/auth/email-code-form.js +18 -77
  47. package/dist/auth/forgot-password-form.js +10 -10
  48. package/dist/auth/forgot-password-page.js +2 -2
  49. package/dist/auth/resend-code-button.js +29 -0
  50. package/dist/auth/sign-in-form.js +7 -8
  51. package/dist/auth/sign-in-page.js +3 -3
  52. package/dist/auth/sign-in-prompt.js +13 -9
  53. package/dist/auth/sign-up-code-form.js +22 -0
  54. package/dist/auth/sign-up-details-form.js +81 -111
  55. package/dist/auth/sign-up-page.js +17 -8
  56. package/dist/auth/two-factor-form.js +3 -3
  57. package/dist/auth/use-sign-in-address.js +21 -8
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.js +2 -1
  60. package/dist/lib/flip-guard.js +43 -0
  61. package/dist/lib/page-scroll-lock.js +20 -0
  62. package/dist/lib/use-focus-trap.js +4 -4
  63. package/dist/organizations/invitation-page.js +7 -6
  64. package/dist/package.js +1 -1
  65. package/dist/primitives/otp-input.d.ts +21 -0
  66. package/dist/primitives/otp-input.js +117 -0
  67. package/dist/primitives/otp-value.js +23 -0
  68. package/dist/primitives/route-link.d.ts +1 -0
  69. package/dist/primitives/route-link.js +20 -0
  70. package/dist/primitives/textarea.js +36 -0
  71. package/dist/record-view/field.js +56 -53
  72. package/dist/shell/assets/app-DJAZP1yB.js +66 -0
  73. package/dist/shell/assets/index-C5pYkUfv.css +2 -0
  74. package/dist/shell/assets/{index-CrtAqGCx.js → index-LBhMBiK4.js} +1 -1
  75. package/dist/shell/assets/maplibre-Dy0ZTnFZ.js +814 -0
  76. package/dist/shell/assets/record-map-BiWSbqqT.js +1 -0
  77. package/dist/shell/assets/records-map-DabYc3ad.js +1 -0
  78. package/dist/shell/assets/shared-protobase-ui-BURelnPG.js +1 -0
  79. package/dist/shell/index.html +6 -6
  80. package/dist/shell/protobase.shell.json +1 -1
  81. package/dist/styles.css +15 -0
  82. package/dist/toasts/toast.js +22 -6
  83. package/package.json +4 -4
  84. package/dist/auth/code-input.js +0 -17
  85. package/dist/auth/sign-in-address.js +0 -47
  86. package/dist/shell/assets/app-CpFoFNtG.js +0 -66
  87. package/dist/shell/assets/index-ibaHR5wQ.css +0 -2
  88. package/dist/shell/assets/maplibre-gl-B_TZ9n3D.js +0 -1
  89. package/dist/shell/assets/record-map-B2mkMEcE.js +0 -814
  90. package/dist/shell/assets/records-map-CAj21Al1.js +0 -1
  91. package/dist/shell/assets/shared-protobase-ui-D942ARkw.js +0 -1
  92. /package/dist/shell/assets/{record-map-DBE96hFo.css → maplibre-DBE96hFo.css} +0 -0
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,n,r,s as i,t as a}from"./maplibre-Dy0ZTnFZ.js";import{t as o}from"./jsx-runtime-NZYk81nU.js";var s=e(o(),1),c=({style:e,position:o,zoom:c})=>(0,s.jsxs)(t,{mapLib:a,mapStyle:e,initialViewState:{...o,zoom:c},cooperativeGestures:!0,style:{width:`100%`,height:`100%`},children:[(0,s.jsx)(n,{showCompass:!1}),(0,s.jsx)(r,{latitude:o.latitude,longitude:o.longitude,anchor:`bottom`,children:(0,s.jsx)(i,{"aria-hidden":!0,className:`size-8 fill-primary text-primary-foreground drop-shadow`,strokeWidth:1.5})})]});export{c as RecordMap};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-Cvdyeg_0.js";import{g as n,q as r}from"./app-DJAZP1yB.js";import{a as i,i as a,n as o,o as s,r as c,s as l,t as u}from"./maplibre-Dy0ZTnFZ.js";import{t as d}from"./jsx-runtime-NZYk81nU.js";function f(e,t){if(!e)throw Error(t)}var p=e(t(),1),m=0;function h(e,t,n){if(e.style&&e.style._loaded){let r={...n};return delete r.id,delete r.children,e.addSource(t,r),e.getSource(t)}return null}function g(e,t,n){f(t.id===n.id,`source id changed`),f(t.type===n.type,`source type changed`);let r=``,i=0;for(let e in t)e!==`children`&&e!==`id`&&!s(n[e],t[e])&&(r=e,i++);if(!i)return;let a=t.type;if(a===`geojson`)e.setData(t.data);else if(a===`image`)e.updateImage({url:t.url,coordinates:t.coordinates});else switch(r){case`coordinates`:e.setCoordinates?.(t.coordinates);break;case`url`:e.setUrl?.(t.url);break;case`tiles`:e.setTiles?.(t.tiles);break;default:console.warn(`Unable to update <Source> prop: ${r}`)}}function _(e){let t=(0,p.useContext)(i).map.getMap(),n=(0,p.useRef)(e),[,r]=(0,p.useState)(0),a=(0,p.useMemo)(()=>e.id||`jsx-source-${m++}`,[]);(0,p.useEffect)(()=>{if(t){let e=()=>setTimeout(()=>r(e=>e+1),0);return t.on(`styledata`,e),e(),()=>{if(t.off(`styledata`,e),t.style&&t.style._loaded&&t.getSource(a)){let e=t.getStyle()?.layers;if(e)for(let n of e)n.source===a&&t.removeLayer(n.id);t.removeSource(a)}}}},[t]);let o=t&&t.style&&t.getSource(a);return o?g(o,e,n.current):o=h(t,a,e),n.current=e,o&&p.Children.map(e.children,e=>e&&(0,p.cloneElement)(e,{source:a}))||null}function v(e,t,n,r){if(f(n.id===r.id,`layer id changed`),f(n.type===r.type,`layer type changed`),n.type===`custom`||r.type===`custom`)return;let{layout:i={},paint:a={},filter:o,minzoom:c,maxzoom:l,beforeId:u}=n;if(u!==r.beforeId&&e.moveLayer(t,u),i!==r.layout){let n=r.layout||{};for(let r in i)s(i[r],n[r])||e.setLayoutProperty(t,r,i[r]);for(let r in n)i.hasOwnProperty(r)||e.setLayoutProperty(t,r,void 0)}if(a!==r.paint){let n=r.paint||{};for(let r in a)s(a[r],n[r])||e.setPaintProperty(t,r,a[r]);for(let r in n)a.hasOwnProperty(r)||e.setPaintProperty(t,r,void 0)}s(o,r.filter)||e.setFilter(t,o),(c!==r.minzoom||l!==r.maxzoom)&&e.setLayerZoomRange(t,c,l)}function y(e,t,n){if(e.style&&e.style._loaded&&(!(`source`in n)||e.getSource(n.source))){let r={...n,id:t};delete r.beforeId,e.addLayer(r,n.beforeId)}}var b=0;function x(e){let t=(0,p.useContext)(i).map.getMap(),n=(0,p.useRef)(e),[,r]=(0,p.useState)(0),a=(0,p.useMemo)(()=>e.id||`jsx-layer-${b++}`,[]);if((0,p.useEffect)(()=>{if(t){let e=()=>r(e=>e+1);return t.on(`styledata`,e),e(),()=>{t.off(`styledata`,e),t.style&&t.style._loaded&&t.getLayer(a)&&t.removeLayer(a)}}},[t]),t&&t.style&&t.getLayer(a))try{v(t,a,e,n.current)}catch(e){console.warn(e)}else y(t,a,e);return n.current=e,null}var S=512,C=85.051129,w=16,T=Array.from({length:23},(e,t)=>t),E=e=>e.type===`LineString`?e.coordinates:e.type===`MultiPolygon`?e.coordinates.flat(2):e.coordinates.flat(),D=e=>{let t=Math.max(-85.051129,Math.min(C,e))*Math.PI/180;return .5-Math.log(Math.tan(Math.PI/4+t/2))/(2*Math.PI)},O=e=>{let t=E(e),n=t.map(([e])=>e),r=t.map(([,e])=>D(e)),i=(Math.max(...n)-Math.min(...n))/360*S,a=(Math.max(...r)-Math.min(...r))*S;return Math.max(i,a)},k=(e,t)=>{let n=e.flatMap(e=>{if(!e.area)return[];let n=e.area.type===`LineString`||e.area.type===`MultiLineString`?`line`:`polygon`;return[{type:`Feature`,geometry:e.area,properties:{key:e.key,kind:n,span:O(e.area),chosen:t?.includes(e.key)??!1}}]});return{type:`FeatureCollection`,features:[...n.filter(e=>!e.properties.chosen),...n.filter(e=>e.properties.chosen)]}},A=e=>[`interpolate`,[`linear`],[`zoom`],...T.flatMap(t=>[t,[`*`,e,[`min`,1,[`max`,0,[`/`,[`-`,[`*`,[`get`,`span`],2**t],w],32]]]]])],j=e(d(),1),M=[`==`,[`get`,`kind`],`polygon`],N=[`==`,[`get`,`kind`],`line`],P=(e,t)=>[`case`,[`get`,`chosen`],e,t],F=({points:e,selected:t,colors:n})=>{let r=k(e,t);if(r.features.length===0)return null;let i=[`case`,[`get`,`chosen`],n.chosen,n.area];return(0,j.jsxs)(_,{id:`position-areas`,type:`geojson`,data:r,children:[(0,j.jsx)(x,{id:`position-area-fills`,type:`fill`,filter:M,paint:{"fill-color":i,"fill-opacity":A(P(.15,.1))}}),(0,j.jsx)(x,{id:`position-area-outlines`,type:`line`,filter:M,paint:{"line-color":i,"line-width":1.5,"line-dasharray":[3,2],"line-opacity":A(.8)}}),(0,j.jsx)(x,{id:`position-area-lines`,type:`line`,filter:N,layout:{"line-cap":`round`,"line-join":`round`},paint:{"line-color":i,"line-width":6,"line-opacity":A(P(.6,.35))}})]})},I=(e,t)=>{let n=document.createElement(`span`);n.style.color=`var(${t})`,e.append(n);let r=getComputedStyle(n).color;n.remove();let i=document.createElement(`canvas`);i.width=1,i.height=1;let a=i.getContext(`2d`,{willReadFrequently:!0});if(!a)return r;a.fillStyle=r,a.fillRect(0,0,1,1);let[o,s,c,l]=a.getImageData(0,0,1,1).data;return`rgba(${o}, ${s}, ${c}, ${l/255})`},L=28,R={padding:48,maxZoom:15,duration:0},z={padding:48,maxZoom:16,duration:300},B=32,V=new Intl.NumberFormat(`en-IE`,{notation:`compact`,maximumFractionDigits:1}),H=e=>[[e.west,e.south],[e.east,e.north]],U=({style:e,initial:t,points:i,buckets:s,fit:d,onFitted:f,onMove:m,selected:h,covered:g,onSelect:_,onClear:v,markerLabel:y,bucketLabel:b})=>{let x=(0,p.useRef)(null),[S,C]=(0,p.useState)([]),[w,T]=(0,p.useState)(),E=new globalThis.Map(i.map(e=>[e.key,e])),D=i.map(e=>e.key).join(`,`),O=d&&JSON.stringify(d),k=()=>{let e=x.current?.getMap();e&&C(n(i.map(t=>({key:t.key,...e.project([t.longitude,t.latitude])})),L))},A=()=>{let e=x.current?.getMap();if(!e)return;let t=e.getBounds(),n=e.getCenter();m({bounds:{south:t.getSouth(),west:t.getWest(),north:t.getNorth(),east:t.getEast()},zoom:e.getZoom()},{latitude:n.lat,longitude:n.lng,zoom:e.getZoom()})},M=()=>{let e=x.current?.getMap();e&&d&&(e.fitBounds(H(d),R),f(),A())};(0,p.useEffect)(k,[D]),(0,p.useEffect)(M,[O]);let N=S.find(e=>h!==void 0&&e.keys.some(e=>h.includes(e)))?.at;return(0,p.useEffect)(()=>{let e=x.current?.getMap(),t=N===void 0?void 0:E.get(N);if(!e||!t||g===0)return;let{y:n}=e.project([t.longitude,t.latitude]),r=e.getContainer().clientHeight-g;n>B&&n<r||e.easeTo({center:[t.longitude,t.latitude],offset:[0,(B-g)/2],duration:300})},[N,g]),(0,j.jsxs)(a,{ref:x,mapLib:u,mapStyle:e,initialViewState:t??{latitude:0,longitude:0,zoom:1},style:{width:`100%`,height:`100%`},onLoad:()=>{let e=x.current.getMap().getContainer();T({area:I(e,`--primary`),chosen:I(e,`--foreground`)}),k(),d?M():A()},onZoomEnd:k,onMoveEnd:A,onClick:v,children:[(0,j.jsx)(o,{showCompass:!1}),w&&(0,j.jsx)(F,{points:i,selected:h,colors:w}),s.map(e=>(0,j.jsx)(c,{latitude:e.latitude,longitude:e.longitude,anchor:`center`,children:(0,j.jsx)(`button`,{type:`button`,"aria-label":b(e.count),className:`flex size-10 cursor-pointer items-center justify-center rounded-full border-2 border-background bg-primary text-xs font-semibold text-primary-foreground tabular-nums shadow`,onClick:t=>{t.stopPropagation(),x.current?.getMap().fitBounds(H(e.bounds),z)},children:V.format(e.count)})},`${e.latitude},${e.longitude}`)),S.map(e=>{let t=E.get(e.at);if(!t)return null;let n=h!==void 0&&e.keys.some(e=>h.includes(e)),i=e.keys.every(e=>E.get(e)?.approximate);return(0,j.jsx)(c,{latitude:t.latitude,longitude:t.longitude,anchor:`bottom`,style:{zIndex:+!!n},children:(0,j.jsxs)(`button`,{type:`button`,"aria-label":y(e.keys),"aria-pressed":n,className:`relative block cursor-pointer`,onClick:t=>{t.stopPropagation(),_(e.keys)},children:[(0,j.jsx)(l,{"aria-hidden":!0,"data-approximate":i||void 0,className:r(`size-8 drop-shadow`,i?n?`fill-background text-foreground`:`fill-background text-primary`:n?`fill-foreground text-background`:`fill-primary text-primary-foreground`),strokeWidth:i?2:1.5,strokeDasharray:i?`3 2`:void 0}),e.keys.length>1&&(0,j.jsx)(`span`,{className:`absolute -right-2 -top-1 min-w-5 rounded-full border border-background bg-foreground px-1 text-center text-[11px] font-medium leading-4 text-background tabular-nums`,children:e.keys.length})]})},e.at)})]})};export{U as RecordsMap};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{A as t,B as n,C as r,D as i,E as a,F as o,G as s,H as c,I as l,K as u,L as d,M as f,N as p,O as m,P as h,R as g,S as _,T as v,U as y,V as b,W as x,_ as S,a as C,b as w,c as T,d as E,f as D,h as O,i as k,j as A,l as j,m as M,n as N,o as P,p as F,r as I,s as L,t as R,u as z,v as B,w as V,x as H,y as U,z as W}from"./app-DJAZP1yB.js";import{t as G}from"./jsx-runtime-NZYk81nU.js";var K=e(G(),1),q=({row:e,resource:t,recordKey:n,...r})=>{let i=O(),a=z(),o=t??i?.resource??a?.model.name;if(o===void 0)throw Error(`RecordLink needs a resource outside a list display or a record`);return(0,K.jsx)(U,{to:{kind:`record`,resource:o,key:e?e.key:n},...r})};export{l as ActionCard,y as ApiProvider,R as App,U as AppLink,V as AssistantDock,n as ChatMessage,W as ChatThread,h as CompactTable,g as Composer,A as DiffView,o as FieldList,u as OtpInput,a as PartView,q as RecordLink,B as ResponsiveDialog,d as SidePanel,S as SignInPrompt,t as StepList,i as definePlugin,m as defineUi,f as diffStats,N as isConflict,T as mergeUi,p as parseDiff,C as pluginApi,P as protobaseVersion,j as uiFromModule,c as useApiToken,w as useAppAddress,r as useAssistant,_ as useAssistantClient,v as useBackendData,x as useClient,E as useFacets,D as useHistogram,z as useLayoutRecord,k as useList,M as useListDisplay,H as useMeta,L as usePlugin,b as useRecord,s as useResourceClient,F as useSeries,I as useUpdateRecord};
@@ -16,19 +16,19 @@
16
16
  }
17
17
  document.documentElement.dataset.theme = stored === 'light' || stored === 'dark' ? stored : matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
18
18
  </script>
19
- <script type="importmap">{"imports":{"react":"/assets/shared-react-DhkZ2M4l.js","react/jsx-runtime":"/assets/shared-react-jsx-runtime-xPQrWk0g.js","react-dom":"/assets/shared-react-dom-D508a1cq.js","@protobase/ui":"/assets/shared-protobase-ui-D942ARkw.js"}}</script>
20
- <script type="module" crossorigin src="/assets/index-CrtAqGCx.js"></script>
19
+ <script type="importmap">{"imports":{"react":"/assets/shared-react-DhkZ2M4l.js","react/jsx-runtime":"/assets/shared-react-jsx-runtime-xPQrWk0g.js","react-dom":"/assets/shared-react-dom-D508a1cq.js","@protobase/ui":"/assets/shared-protobase-ui-BURelnPG.js"}}</script>
20
+ <script type="module" crossorigin src="/assets/index-LBhMBiK4.js"></script>
21
21
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
22
22
  <link rel="modulepreload" crossorigin href="/assets/react-Cvdyeg_0.js">
23
23
  <link rel="modulepreload" crossorigin href="/assets/react-dom-B-VxWsjA.js">
24
24
  <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-NZYk81nU.js">
25
- <link rel="modulepreload" crossorigin href="/assets/app-CpFoFNtG.js">
25
+ <link rel="modulepreload" crossorigin href="/assets/app-DJAZP1yB.js">
26
26
  <link rel="stylesheet" crossorigin href="/assets/app-GUjJKojE.css">
27
- <link rel="stylesheet" crossorigin href="/assets/index-ibaHR5wQ.css">
27
+ <link rel="stylesheet" crossorigin href="/assets/index-C5pYkUfv.css">
28
28
  <link rel="stylesheet" href="/protobase.theme.css">
29
29
  </head>
30
30
  <body>
31
- <!-- The page reaches under the iPhone home indicator, which the bottom bar keeps clear of; the sides keep clear of the notch. -->
32
- <div id="root" class="h-screen" style="padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right)"></div>
31
+ <!-- As tall as the screen shows, browser toolbars aside, so a page that fills it, such as a map, keeps the bottom bar in view. The page reaches under the iPhone home indicator, which the bottom bar keeps clear of; the sides keep clear of the notch. -->
32
+ <div id="root" class="h-dvh" style="padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right)"></div>
33
33
  </body>
34
34
  </html>
@@ -1,5 +1,5 @@
1
1
  {
2
- "protobase": "0.15.4",
2
+ "protobase": "0.16.0",
3
3
  "pluginApi": 1,
4
4
  "paths": [
5
5
  "/index.html",
package/dist/styles.css CHANGED
@@ -12,6 +12,10 @@
12
12
  html[data-theme="dark"] {
13
13
  color-scheme: dark;
14
14
  }
15
+ /* A modal's scroll lock hides the page's scrollbar; its room stays, so the page behind keeps its width. */
16
+ html[data-pb-scroll-locked] {
17
+ scrollbar-gutter: stable;
18
+ }
15
19
  body {
16
20
  background: var(--background);
17
21
  color: var(--foreground);
@@ -23,6 +27,17 @@
23
27
  button {
24
28
  cursor: pointer;
25
29
  }
30
+ /* Asked for less motion, nothing animates or fades: it changes at once, and nothing that pulses keeps on. */
31
+ @media (prefers-reduced-motion: reduce) {
32
+ *,
33
+ ::before,
34
+ ::after {
35
+ animation-duration: 0.01ms !important;
36
+ animation-iteration-count: 1 !important;
37
+ transition-duration: 0.01ms !important;
38
+ scroll-behavior: auto !important;
39
+ }
40
+ }
26
41
  * {
27
42
  border-color: var(--border);
28
43
  }
@@ -1,8 +1,29 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { inApp } from "../app-shell/breadcrumb.js";
2
3
  import { Spinner } from "../primitives/spinner.js";
3
4
  import { CheckCircle2, X, XCircle } from "lucide-react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/toasts/toast.tsx
7
+ const actionClass = "-my-0.5 rounded px-1.5 py-0.5 text-[13px] font-medium text-primary-text hover:bg-primary-soft";
8
+ const Action = ({ action }) => {
9
+ if ("onClick" in action) return /* @__PURE__ */ jsx("button", {
10
+ type: "button",
11
+ onClick: action.onClick,
12
+ className: actionClass,
13
+ children: action.label
14
+ });
15
+ const { href, onNavigate } = action;
16
+ return /* @__PURE__ */ jsx("a", {
17
+ href,
18
+ onClick: (event) => {
19
+ if (!onNavigate || !inApp(event)) return;
20
+ event.preventDefault();
21
+ onNavigate(href);
22
+ },
23
+ className: actionClass,
24
+ children: action.label
25
+ });
26
+ };
6
27
  const icons = {
7
28
  loading: /* @__PURE__ */ jsx(Spinner, { className: "text-primary" }),
8
29
  success: /* @__PURE__ */ jsx(CheckCircle2, { className: "size-4 text-success" }),
@@ -26,12 +47,7 @@ const Toast = ({ state, title, description, action, onDismiss }) => /* @__PURE__
26
47
  children: description
27
48
  })]
28
49
  }),
29
- action && /* @__PURE__ */ jsx("button", {
30
- type: "button",
31
- onClick: action.onClick,
32
- className: "rounded px-1.5 py-0.5 text-[13px] font-medium text-primary-text hover:bg-primary-soft",
33
- children: action.label
34
- }),
50
+ action && /* @__PURE__ */ jsx(Action, { action }),
35
51
  onDismiss && /* @__PURE__ */ jsx("button", {
36
52
  type: "button",
37
53
  "aria-label": "Dismiss",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/ui",
3
- "version": "0.15.4",
3
+ "version": "0.16.0",
4
4
  "description": "The Protobase admin app and the React hooks and components for custom UI.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -38,9 +38,9 @@
38
38
  "dependencies": {
39
39
  "@dnd-kit/core": "^6.3.1",
40
40
  "@dnd-kit/sortable": "^10.0.0",
41
- "@protobase/client": "0.15.4",
42
- "@protobase/layout": "0.15.4",
43
- "@protobase/schema": "0.15.4",
41
+ "@protobase/client": "0.16.0",
42
+ "@protobase/layout": "0.16.0",
43
+ "@protobase/schema": "0.16.0",
44
44
  "@sentry/browser": "^11.7.0",
45
45
  "@tanstack/react-query": "^5.104.1",
46
46
  "@tanstack/react-table": "^9.2.6",
@@ -1,17 +0,0 @@
1
- import { cn } from "../lib/cn.js";
2
- import { Input } from "../primitives/input.js";
3
- import { jsx } from "react/jsx-runtime";
4
- //#region src/auth/code-input.tsx
5
- /** A 6-digit one-time code field: digits on phone keyboards, filled from the mail app where the system offers it. */
6
- const CodeInput = ({ className, ...rest }) => /* @__PURE__ */ jsx(Input, {
7
- type: "text",
8
- inputMode: "numeric",
9
- autoComplete: "one-time-code",
10
- pattern: "[0-9]{6}",
11
- maxLength: 6,
12
- spellCheck: false,
13
- className: cn("min-h-6 font-mono tracking-[0.3em]", className),
14
- ...rest
15
- });
16
- //#endregion
17
- export { CodeInput };
@@ -1,47 +0,0 @@
1
- //#region src/auth/sign-in-address.ts
2
- /** The path of the sign-in route, below the app's base path. Its steps and the page to come back to are in its query. */
3
- const signInRoute = "/-/sign-in";
4
- /** The names of the sign-in route's query parameters: the step it shows, and the page to come back to after it. */
5
- const signInParams = {
6
- step: "step",
7
- next: "next"
8
- };
9
- /**
10
- * A step of signing in or making an account, each with an address of its own: Back from a step returns to the one
11
- * before. `email-code` and `sign-up-code` enter the code emailed to an address the step before asked for.
12
- */
13
- const signInSteps = [
14
- "sign-in",
15
- "forgot-password",
16
- "email-code",
17
- "sign-up",
18
- "sign-up-code"
19
- ];
20
- const isStep = (value) => signInSteps.includes(value);
21
- const localPage = (next) => {
22
- if (!next?.startsWith("/")) return void 0;
23
- const url = new URL(next, "http://local");
24
- if (url.origin !== "http://local" || url.pathname === "/-/sign-in") return void 0;
25
- return `${url.pathname}${url.search}`;
26
- };
27
- /** The path below the base path of a step of the sign-in route, coming back to `next` after it, the start by default. */
28
- const signInPath = ({ step = "sign-in", next } = {}) => {
29
- const params = new URLSearchParams();
30
- if (step !== "sign-in") params.set(signInParams.step, step);
31
- const page = localPage(next);
32
- if (page && page !== "/") params.set(signInParams.next, page);
33
- const query = params.toString();
34
- return query ? `${signInRoute}?${query}` : signInRoute;
35
- };
36
- /** The sign-in route's step and the page to come back to, for the path below the base path; `undefined` elsewhere. */
37
- const readSignInAddress = (path, params) => {
38
- if (path !== "/-/sign-in") return void 0;
39
- const step = params.get(signInParams.step);
40
- const next = localPage(params.get(signInParams.next));
41
- return {
42
- step: isStep(step) ? step : "sign-in",
43
- ...next && { next }
44
- };
45
- };
46
- //#endregion
47
- export { readSignInAddress, signInParams, signInPath, signInRoute, signInSteps };