@contractspec/lib.design-system 4.4.0 → 4.4.2
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/README.md +11 -6
- package/dist/browser/components/shell/AppShell.js +1 -1
- package/dist/browser/components/shell/PageOutline.js +1 -1
- package/dist/browser/components/shell/ShellNotifications.js +1 -1
- package/dist/browser/components/shell/ShellSidebar.js +1 -1
- package/dist/browser/renderers/form-contract/phone-country-control.js +1 -1
- package/dist/browser/renderers/form-contract/phone-country-utils.js +1 -1
- package/dist/browser/renderers/form-contract/phone-field.js +1 -1
- package/dist/components/shell/AppShell.js +1 -1
- package/dist/components/shell/PageOutline.d.ts +1 -1
- package/dist/components/shell/PageOutline.js +1 -1
- package/dist/components/shell/PageOutline.native.d.ts +1 -0
- package/dist/components/shell/ShellNotifications.js +1 -1
- package/dist/components/shell/ShellSidebar.d.ts +2 -1
- package/dist/components/shell/ShellSidebar.js +1 -1
- package/dist/native/components/shell/AppShell.js +1 -1
- package/dist/native/components/shell/PageOutline.js +1 -1
- package/dist/native/components/shell/ShellNotifications.js +1 -1
- package/dist/native/components/shell/ShellSidebar.js +1 -1
- package/dist/native/renderers/form-contract/phone-country-control.js +1 -1
- package/dist/native/renderers/form-contract/phone-country-control.native.js +1 -1
- package/dist/native/renderers/form-contract/phone-country-utils.js +1 -1
- package/dist/native/renderers/form-contract/phone-field.js +1 -1
- package/dist/renderers/form-contract/phone-country-control.js +1 -1
- package/dist/renderers/form-contract/phone-country-utils.d.ts +2 -2
- package/dist/renderers/form-contract/phone-country-utils.js +1 -1
- package/dist/renderers/form-contract/phone-field.js +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -231,17 +231,22 @@ import { AppShell } from "@contractspec/lib.design-system/shell";
|
|
|
231
231
|
</AppShell>;
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
On desktop web, `AppShell` renders a sidebar, sticky topbar, content
|
|
235
|
-
optional `PageOutline
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
On desktop web, `AppShell` renders a collapsible sidebar, sticky topbar, content
|
|
235
|
+
region, and optional floating `PageOutline`. The outline does not reserve a
|
|
236
|
+
right-side content column: it reduces to a slim rail while inactive and expands
|
|
237
|
+
on hover or keyboard focus, keeping wide page content centered. The desktop
|
|
238
|
+
topbar is inset beside the sidebar and includes a sidebar toggle. On small web
|
|
239
|
+
screens, navigation and page outline move behind accessible menu triggers. On
|
|
240
|
+
native, the shell maps primary navigation to bottom tabs and keeps overflow
|
|
241
|
+
navigation, actions, user content, and page outline inside the menu sheet.
|
|
239
242
|
|
|
240
243
|
`AppShell` also accepts a prop-driven `notifications` center for in-app
|
|
241
244
|
notifications. Hosts provide structural `items`, `unreadCount`, loading/empty
|
|
242
245
|
state, and callbacks such as `onSelect`, `onMarkRead`, and `onMarkAllRead`; the
|
|
243
246
|
design-system shell renders the web topbar trigger and native menu section
|
|
244
|
-
without importing or owning any notification runtime package.
|
|
247
|
+
without importing or owning any notification runtime package. On web, the
|
|
248
|
+
notification panel closes when users select an item, press the close button,
|
|
249
|
+
click outside the panel, press Escape, or click the notification trigger again.
|
|
245
250
|
|
|
246
251
|
Shell navigation and command items may carry optional `policy` metadata plus a `policyBehavior` of `hide`, `disable`, or `show-with-lock`. Use `filterShellNavigationForPolicy()` / `annotateShellCommandsDecisions()` with decisions produced by your application runtime; AppShell only adapts affordances and does not fetch permissions or enforce backend access.
|
|
247
252
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as k,jsxs as
|
|
1
|
+
import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as D,jsxs as
|
|
1
|
+
import{jsx as D,jsxs as J,Fragment as F}from"react/jsx-runtime";import{cn as X}from"@contractspec/lib.ui-kit-web/ui/utils";import{BellIcon as B,CheckIcon as q,XIcon as I}from"lucide-react";import*as Y from"react";import{Button as Z}from"../atoms/Button";function E(z){return z.status==="unread"||!z.status&&!z.readAt}function k(z){if(!z)return;return z instanceof Date?z.toLocaleString():z}export function ShellNotifications({notifications:z}){const[G,$]=Y.useState(!1),K=Y.useRef(null),W=Y.useRef(null),M=z.items??[],P=z.unreadCount??M.filter((H)=>E(H)).length,Q=z.label??"Notifications",U=z.emptyLabel??"No notifications",L=z.markAllReadLabel??"Mark all notifications as read",V=Y.useCallback((H)=>{$(H);z.onOpenChange?.(H)},[z]);Y.useEffect(()=>{if(!G)return;const H=(A)=>{const S=A.target;if(!(S instanceof Node))return;if(K.current?.contains(S)||W.current?.contains(S))return;V(!1)},T=(A)=>{if(A.key==="Escape")V(!1)};document.addEventListener("click",H,!0);document.addEventListener("keydown",T);return()=>{document.removeEventListener("click",H,!0);document.removeEventListener("keydown",T)}},[G,V]);return J(F,{children:[D("span",{ref:W,className:"inline-flex",children:J(Z,{variant:"ghost",size:"icon",className:"relative","aria-expanded":G,"aria-haspopup":"dialog",ariaLabelI18n:Q,onPress:()=>V(!G),children:[D(B,{className:"h-4 w-4"}),P>0?D("span",{"aria-label":`${P} unread notifications`,className:"absolute -top-1 -right-1 inline-flex min-h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 font-medium text-[10px] text-destructive-foreground leading-none",children:P>99?"99+":P}):null]})}),G?J("div",{ref:K,"aria-label":Q,"aria-modal":"false",className:"fixed top-16 right-4 z-50 max-h-[calc(100svh-5rem)] w-[min(24rem,calc(100vw-2rem))] overflow-auto rounded-md border bg-background p-4 shadow-lg",role:"dialog",children:[J("div",{className:"mb-3 flex items-center justify-between gap-3",children:[D("h2",{className:"font-semibold text-lg",children:Q}),J("div",{className:"flex items-center gap-1",children:[M.length>0&&z.onMarkAllRead?J(Z,{variant:"ghost",size:"sm",ariaLabelI18n:L,onPress:z.onMarkAllRead,children:[D(q,{className:"h-4 w-4"}),D("span",{children:"Mark all read"})]}):null,D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:"Close notifications",onPress:()=>V(!1),children:D(I,{className:"h-4 w-4"})})]})]}),D("div",{className:"flex flex-col gap-2",children:z.loading?D("div",{"aria-live":"polite",className:"py-6 text-center text-muted-foreground text-sm",children:"Loading notifications..."}):M.length?M.map((H)=>D(C,{item:H,notifications:z,onClose:()=>V(!1)},H.id)):D("div",{className:"py-6 text-center text-muted-foreground text-sm",children:U})})]}):null]})}function C({item:z,notifications:G,onClose:$}){const K=E(z),W=k(z.createdAt),M=()=>{G.onSelect?.(z);$()},P=()=>G.onMarkRead?.(z);if(G.renderItem)return D("div",{className:X("rounded-xs border p-3",K&&"bg-muted/50"),children:G.renderItem(z,{unread:K,onSelect:M,onMarkRead:P})});const Q=D(F,{children:J("span",{className:"flex min-w-0 flex-1 flex-col gap-1 text-left",children:[J("span",{className:"flex items-center gap-2",children:[K?D("span",{className:"h-2 w-2 rounded-full bg-primary","aria-hidden":!0}):null,D("span",{className:"font-medium text-sm",children:z.title})]}),z.body?D("span",{className:"text-muted-foreground text-sm",children:z.body}):null,J("span",{className:"flex flex-wrap items-center gap-2 text-muted-foreground text-xs",children:[z.category?D("span",{children:z.category}):null,W?D("time",{children:W}):null]})]})});return J("div",{className:X("flex items-start gap-2 rounded-xs border p-3",K&&"bg-muted/50"),children:[z.actionUrl?D("a",{href:z.actionUrl,className:"min-w-0 flex-1",onClick:M,children:Q}):D("button",{type:"button",className:"min-w-0 flex-1",onClick:M,children:Q}),K&&G.onMarkRead?D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:`Mark ${String(z.title)} as read`,onPress:P,children:D(q,{className:"h-4 w-4"})}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as
|
|
1
|
+
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as L,SidebarContent as R,SidebarFooter as B,SidebarGroup as K,SidebarGroupContent as N,SidebarGroupLabel as C,SidebarHeader as G,SidebarMenu as Z,SidebarMenuBadge as I,SidebarMenuButton as P,SidebarMenuItem as T,SidebarProvider as M,SidebarRail as p}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as $}from"@contractspec/lib.ui-kit-web/ui/utils";function g(q,D){if(q.active)return!0;if(!D||!q.href)return!1;return q.match==="startsWith"?D.startsWith(q.href):D===q.href}function k(q){return q.key??q.href??String(q.label)}function A({item:q,activeHref:D,depth:J=0}){const U=g(q,D),E=q.disabled||q.policyDecision?.effect==="deny",X=Boolean(q.children?.length),V=Q("span",{className:$("inline-flex min-w-0 items-center gap-2",J>0&&"pl-4"),children:[q.icon,z("span",{className:"truncate",children:q.label})]});return Q(T,{children:[z(P,{asChild:!!q.href&&!E,isActive:U,"aria-disabled":E,"aria-label":q.href&&!E?void 0:q.ariaLabel,disabled:E,onClick:q.href||E?void 0:()=>q.onSelect?.(),children:q.href&&!E?z("a",{href:q.href,target:q.target,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),children:V}):V}),q.badge!=null&&z(I,{children:q.badge}),X&&z(Z,{className:"mt-1",children:q.children?.map((O)=>z(A,{item:O,activeHref:D,depth:J+1},k(O)))})]})}export function ShellSidebar({sections:q,brand:D,commandTrigger:J,footer:U,activeHref:E,className:X,withProvider:V=!0}){const O=Q(L,{className:X,children:[z(p,{}),Q(G,{className:$("gap-3",!D&&!J&&"hidden"),children:[D,J]}),z(R,{children:q.map((W,F)=>Q(K,{children:[W.title&&z(C,{children:W.title}),z(N,{children:z(Z,{children:W.items.map((Y)=>z(A,{item:Y,activeHref:E},k(Y)))})})]},W.key??F))}),U&&z(B,{children:U})]});return V?z(M,{children:O}):O}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as
|
|
1
|
+
import{jsx as z,jsxs as k}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{Select as Q}from"../../components/forms/controls/Select";import{HStack as U}from"../../components/layout/Stack";import{optionValue as W}from"../../components/primitives/control";import{useTranslatedText as Y}from"../../components/primitives/themed";import{countryCallingCode as Z,countryFlag as $}from"./phone-country-utils";import{FORM_FALLBACK_TEXT as J}from"./values";export function PhoneFlag(b){if(b.hidden)return null;const q=$(b.iso2);if(!q)return null;return z("span",{"aria-label":b.iso2,className:"shrink-0 text-lg",role:"img",children:q})}export function PhoneCountryControl(b){const q=Y(),D=b.display.countrySelect;return k(U,{align:"center",gap:"sm",children:[z(PhoneFlag,{iso2:b.countryIso2,hidden:D||!b.display.flag}),D?z(Q,{id:b.id,name:b.name,value:b.selectValue,onChange:(G)=>b.onCountryChange(W(G)),options:b.selectOptions,disabled:b.disabled||b.readOnly}):z(N,{id:b.id,name:b.name,value:b.countryCode,onChange:(G)=>b.onCountryChange(G.currentTarget.value),placeholder:q(b.parts?.placeholdersI18n?.countryCode??J.countryCode),"aria-label":q(J.countryCode),readOnly:b.readOnly,disabled:b.disabled}),!D&&b.display.callingCode?z("span",{className:"min-w-12 text-muted-foreground text-sm",children:Z(b.countryIso2)||b.countryCode}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"country-flag-icons/unicode";import{getCountries as a,getCountryCallingCode as u}from"libphonenumber-js/min";const c=a();export function normalizeIso2(e){const n=e?.trim().toUpperCase();return n&&c.includes(n)?n:void 0}export function countryCallingCode(e){const n=normalizeIso2(e);return n?`+${u(n)}`:""}export function countryFlag(e){const n=normalizeIso2(e);return n?s(n):""}function l(e){const n=e?.allowedIso2?.map((o)=>normalizeIso2(o)).filter((o)=>Boolean(o));return n?.length?n:c}export function isAllowedPhoneCountry(e,n){const o=normalizeIso2(e);return Boolean(o&&l(n).includes(o))}export function countryFromCallingCode(e,n,o){const t=e?.trim().replace(/^\+/,"");if(!t)return;const r=l(n),i=normalizeIso2(o);if(i&&r.includes(i)&&u(i)===t)return i;return r.find((d)=>u(d)===t)}export function countryFromInput(e,n,o){const t=e?.trim(),r=normalizeIso2(t);return(r&&isAllowedPhoneCountry(r,n)?r:void 0)??countryFromCallingCode(t,n,o)}export function phoneCountryOptions(e,n){return l(e).map((o)=>{const t=countryCallingCode(o);return{labelI18n:[n?.flag===!1?void 0:countryFlag(o),o,n?.callingCode===!1?void 0:t].filter((i)=>Boolean(i)).join(" "),value:o}})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as
|
|
1
|
+
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as H}from"./values";export const PhoneField=(b)=>{const Z=A(),X=b.input?.mode??"split",g=b.input?.autoSwitch??!0,k=b.country?.detection??"input",W=b.output?.countryCodeFormat,$={flag:b.display?.flag??!0,callingCode:b.display?.callingCode??!0,countrySelect:b.display?.countrySelect??!0,extension:b.display?.extension??!0},G=E(b.value,b.country,W),Y=G.countryIso2,B=b.countryOptions?.length?b.countryOptions:d(b.country,$),M=B.some((q)=>String(q.value).toUpperCase()===Y)?Y:G.countryCode,Q=(q)=>{b.onChange?.(E(q,b.country,W))},S=(q)=>{const J=C(q,b.country,Y);Q({...G,countryIso2:J,countryCode:W==="iso2"?J??q:j(J)||q,e164:void 0})},f=(q)=>{if(g&&k==="input"&&q.trim().startsWith("+")){Q(K(q,G,b.country,W));return}Q({...G,nationalNumber:q,e164:void 0})},P=G.e164||`${G.countryCode}${G.nationalNumber}`,O=U(L,{id:b.id?`${b.id}-country`:void 0,name:b.name?`${b.name}.countryCode`:void 0,countryCode:G.countryCode,countryIso2:Y,selectValue:M,selectOptions:B,parts:b.parts,display:$,disabled:b.disabled,readOnly:b.readOnly,onCountryChange:S});if(X==="single")return U(D,{gap:"sm",children:R(V,{align:"center",gap:"sm",children:[U(T,{iso2:Y,hidden:!$.flag}),U(N,{id:b.id,name:b.name,value:P,onChange:(q)=>{const J=z(q);if(g&&k==="input"&&J.trim().startsWith("+")){Q(K(J,G,b.country,W));return}Q({...G,nationalNumber:J,e164:void 0})},placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled})]})});return R(D,{gap:"sm",children:[O,U(N,{id:b.id,name:b.name,value:G.nationalNumber,onChange:(q)=>f(z(q)),placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel-national"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled}),$.extension?U(N,{id:b.id?`${b.id}-extension`:void 0,name:b.name?`${b.name}.extension`:void 0,value:G.extension??"",onChange:(q)=>Q({...G,extension:z(q)}),placeholder:Z(b.parts?.placeholdersI18n?.extension??H.extension),keyboard:{kind:"number"},"aria-label":Z(H.extension),readOnly:b.readOnly,disabled:b.disabled}):null]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as k,jsxs as
|
|
1
|
+
import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
|
|
@@ -5,7 +5,7 @@ export interface PageOutlineProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
5
5
|
activeId?: string;
|
|
6
6
|
onNavigate?: (item: PageOutlineItem) => void;
|
|
7
7
|
ariaLabel?: string;
|
|
8
|
-
variant?: 'rail' | 'compact';
|
|
8
|
+
variant?: 'rail' | 'compact' | 'floating';
|
|
9
9
|
maxLevel?: PageOutlineLevel;
|
|
10
10
|
}
|
|
11
11
|
export declare function PageOutline({ items, activeId, onNavigate, ariaLabel, variant, maxLevel, className, ...props }: PageOutlineProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as D,jsxs as
|
|
1
|
+
import{jsx as D,jsxs as J,Fragment as F}from"react/jsx-runtime";import{cn as X}from"@contractspec/lib.ui-kit-web/ui/utils";import{BellIcon as B,CheckIcon as q,XIcon as I}from"lucide-react";import*as Y from"react";import{Button as Z}from"../atoms/Button";function E(z){return z.status==="unread"||!z.status&&!z.readAt}function k(z){if(!z)return;return z instanceof Date?z.toLocaleString():z}export function ShellNotifications({notifications:z}){const[G,$]=Y.useState(!1),K=Y.useRef(null),W=Y.useRef(null),M=z.items??[],P=z.unreadCount??M.filter((H)=>E(H)).length,Q=z.label??"Notifications",U=z.emptyLabel??"No notifications",L=z.markAllReadLabel??"Mark all notifications as read",V=Y.useCallback((H)=>{$(H);z.onOpenChange?.(H)},[z]);Y.useEffect(()=>{if(!G)return;const H=(A)=>{const S=A.target;if(!(S instanceof Node))return;if(K.current?.contains(S)||W.current?.contains(S))return;V(!1)},T=(A)=>{if(A.key==="Escape")V(!1)};document.addEventListener("click",H,!0);document.addEventListener("keydown",T);return()=>{document.removeEventListener("click",H,!0);document.removeEventListener("keydown",T)}},[G,V]);return J(F,{children:[D("span",{ref:W,className:"inline-flex",children:J(Z,{variant:"ghost",size:"icon",className:"relative","aria-expanded":G,"aria-haspopup":"dialog",ariaLabelI18n:Q,onPress:()=>V(!G),children:[D(B,{className:"h-4 w-4"}),P>0?D("span",{"aria-label":`${P} unread notifications`,className:"absolute -top-1 -right-1 inline-flex min-h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 font-medium text-[10px] text-destructive-foreground leading-none",children:P>99?"99+":P}):null]})}),G?J("div",{ref:K,"aria-label":Q,"aria-modal":"false",className:"fixed top-16 right-4 z-50 max-h-[calc(100svh-5rem)] w-[min(24rem,calc(100vw-2rem))] overflow-auto rounded-md border bg-background p-4 shadow-lg",role:"dialog",children:[J("div",{className:"mb-3 flex items-center justify-between gap-3",children:[D("h2",{className:"font-semibold text-lg",children:Q}),J("div",{className:"flex items-center gap-1",children:[M.length>0&&z.onMarkAllRead?J(Z,{variant:"ghost",size:"sm",ariaLabelI18n:L,onPress:z.onMarkAllRead,children:[D(q,{className:"h-4 w-4"}),D("span",{children:"Mark all read"})]}):null,D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:"Close notifications",onPress:()=>V(!1),children:D(I,{className:"h-4 w-4"})})]})]}),D("div",{className:"flex flex-col gap-2",children:z.loading?D("div",{"aria-live":"polite",className:"py-6 text-center text-muted-foreground text-sm",children:"Loading notifications..."}):M.length?M.map((H)=>D(C,{item:H,notifications:z,onClose:()=>V(!1)},H.id)):D("div",{className:"py-6 text-center text-muted-foreground text-sm",children:U})})]}):null]})}function C({item:z,notifications:G,onClose:$}){const K=E(z),W=k(z.createdAt),M=()=>{G.onSelect?.(z);$()},P=()=>G.onMarkRead?.(z);if(G.renderItem)return D("div",{className:X("rounded-xs border p-3",K&&"bg-muted/50"),children:G.renderItem(z,{unread:K,onSelect:M,onMarkRead:P})});const Q=D(F,{children:J("span",{className:"flex min-w-0 flex-1 flex-col gap-1 text-left",children:[J("span",{className:"flex items-center gap-2",children:[K?D("span",{className:"h-2 w-2 rounded-full bg-primary","aria-hidden":!0}):null,D("span",{className:"font-medium text-sm",children:z.title})]}),z.body?D("span",{className:"text-muted-foreground text-sm",children:z.body}):null,J("span",{className:"flex flex-wrap items-center gap-2 text-muted-foreground text-xs",children:[z.category?D("span",{children:z.category}):null,W?D("time",{children:W}):null]})]})});return J("div",{className:X("flex items-start gap-2 rounded-xs border p-3",K&&"bg-muted/50"),children:[z.actionUrl?D("a",{href:z.actionUrl,className:"min-w-0 flex-1",onClick:M,children:Q}):D("button",{type:"button",className:"min-w-0 flex-1",onClick:M,children:Q}),K&&G.onMarkRead?D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:`Mark ${String(z.title)} as read`,onPress:P,children:D(q,{className:"h-4 w-4"})}):null]})}
|
|
@@ -7,5 +7,6 @@ export interface ShellSidebarProps {
|
|
|
7
7
|
footer?: React.ReactNode;
|
|
8
8
|
activeHref?: string;
|
|
9
9
|
className?: string;
|
|
10
|
+
withProvider?: boolean;
|
|
10
11
|
}
|
|
11
|
-
export declare function ShellSidebar({ sections, brand, commandTrigger, footer, activeHref, className, }: ShellSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function ShellSidebar({ sections, brand, commandTrigger, footer, activeHref, className, withProvider, }: ShellSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as
|
|
1
|
+
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as L,SidebarContent as R,SidebarFooter as B,SidebarGroup as K,SidebarGroupContent as N,SidebarGroupLabel as C,SidebarHeader as G,SidebarMenu as Z,SidebarMenuBadge as I,SidebarMenuButton as P,SidebarMenuItem as T,SidebarProvider as M,SidebarRail as p}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as $}from"@contractspec/lib.ui-kit-web/ui/utils";function g(q,D){if(q.active)return!0;if(!D||!q.href)return!1;return q.match==="startsWith"?D.startsWith(q.href):D===q.href}function k(q){return q.key??q.href??String(q.label)}function A({item:q,activeHref:D,depth:J=0}){const U=g(q,D),E=q.disabled||q.policyDecision?.effect==="deny",X=Boolean(q.children?.length),V=Q("span",{className:$("inline-flex min-w-0 items-center gap-2",J>0&&"pl-4"),children:[q.icon,z("span",{className:"truncate",children:q.label})]});return Q(T,{children:[z(P,{asChild:!!q.href&&!E,isActive:U,"aria-disabled":E,"aria-label":q.href&&!E?void 0:q.ariaLabel,disabled:E,onClick:q.href||E?void 0:()=>q.onSelect?.(),children:q.href&&!E?z("a",{href:q.href,target:q.target,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),children:V}):V}),q.badge!=null&&z(I,{children:q.badge}),X&&z(Z,{className:"mt-1",children:q.children?.map((O)=>z(A,{item:O,activeHref:D,depth:J+1},k(O)))})]})}export function ShellSidebar({sections:q,brand:D,commandTrigger:J,footer:U,activeHref:E,className:X,withProvider:V=!0}){const O=Q(L,{className:X,children:[z(p,{}),Q(G,{className:$("gap-3",!D&&!J&&"hidden"),children:[D,J]}),z(R,{children:q.map((W,F)=>Q(K,{children:[W.title&&z(C,{children:W.title}),z(N,{children:z(Z,{children:W.items.map((Y)=>z(A,{item:Y,activeHref:E},k(Y)))})})]},W.key??F))}),U&&z(B,{children:U})]});return V?z(M,{children:O}):O}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as k,jsxs as
|
|
1
|
+
import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as D,jsxs as
|
|
1
|
+
import{jsx as D,jsxs as J,Fragment as F}from"react/jsx-runtime";import{cn as X}from"@contractspec/lib.ui-kit-web/ui/utils";import{BellIcon as B,CheckIcon as q,XIcon as I}from"lucide-react";import*as Y from"react";import{Button as Z}from"../atoms/Button";function E(z){return z.status==="unread"||!z.status&&!z.readAt}function k(z){if(!z)return;return z instanceof Date?z.toLocaleString():z}export function ShellNotifications({notifications:z}){const[G,$]=Y.useState(!1),K=Y.useRef(null),W=Y.useRef(null),M=z.items??[],P=z.unreadCount??M.filter((H)=>E(H)).length,Q=z.label??"Notifications",U=z.emptyLabel??"No notifications",L=z.markAllReadLabel??"Mark all notifications as read",V=Y.useCallback((H)=>{$(H);z.onOpenChange?.(H)},[z]);Y.useEffect(()=>{if(!G)return;const H=(A)=>{const S=A.target;if(!(S instanceof Node))return;if(K.current?.contains(S)||W.current?.contains(S))return;V(!1)},T=(A)=>{if(A.key==="Escape")V(!1)};document.addEventListener("click",H,!0);document.addEventListener("keydown",T);return()=>{document.removeEventListener("click",H,!0);document.removeEventListener("keydown",T)}},[G,V]);return J(F,{children:[D("span",{ref:W,className:"inline-flex",children:J(Z,{variant:"ghost",size:"icon",className:"relative","aria-expanded":G,"aria-haspopup":"dialog",ariaLabelI18n:Q,onPress:()=>V(!G),children:[D(B,{className:"h-4 w-4"}),P>0?D("span",{"aria-label":`${P} unread notifications`,className:"absolute -top-1 -right-1 inline-flex min-h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 font-medium text-[10px] text-destructive-foreground leading-none",children:P>99?"99+":P}):null]})}),G?J("div",{ref:K,"aria-label":Q,"aria-modal":"false",className:"fixed top-16 right-4 z-50 max-h-[calc(100svh-5rem)] w-[min(24rem,calc(100vw-2rem))] overflow-auto rounded-md border bg-background p-4 shadow-lg",role:"dialog",children:[J("div",{className:"mb-3 flex items-center justify-between gap-3",children:[D("h2",{className:"font-semibold text-lg",children:Q}),J("div",{className:"flex items-center gap-1",children:[M.length>0&&z.onMarkAllRead?J(Z,{variant:"ghost",size:"sm",ariaLabelI18n:L,onPress:z.onMarkAllRead,children:[D(q,{className:"h-4 w-4"}),D("span",{children:"Mark all read"})]}):null,D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:"Close notifications",onPress:()=>V(!1),children:D(I,{className:"h-4 w-4"})})]})]}),D("div",{className:"flex flex-col gap-2",children:z.loading?D("div",{"aria-live":"polite",className:"py-6 text-center text-muted-foreground text-sm",children:"Loading notifications..."}):M.length?M.map((H)=>D(C,{item:H,notifications:z,onClose:()=>V(!1)},H.id)):D("div",{className:"py-6 text-center text-muted-foreground text-sm",children:U})})]}):null]})}function C({item:z,notifications:G,onClose:$}){const K=E(z),W=k(z.createdAt),M=()=>{G.onSelect?.(z);$()},P=()=>G.onMarkRead?.(z);if(G.renderItem)return D("div",{className:X("rounded-xs border p-3",K&&"bg-muted/50"),children:G.renderItem(z,{unread:K,onSelect:M,onMarkRead:P})});const Q=D(F,{children:J("span",{className:"flex min-w-0 flex-1 flex-col gap-1 text-left",children:[J("span",{className:"flex items-center gap-2",children:[K?D("span",{className:"h-2 w-2 rounded-full bg-primary","aria-hidden":!0}):null,D("span",{className:"font-medium text-sm",children:z.title})]}),z.body?D("span",{className:"text-muted-foreground text-sm",children:z.body}):null,J("span",{className:"flex flex-wrap items-center gap-2 text-muted-foreground text-xs",children:[z.category?D("span",{children:z.category}):null,W?D("time",{children:W}):null]})]})});return J("div",{className:X("flex items-start gap-2 rounded-xs border p-3",K&&"bg-muted/50"),children:[z.actionUrl?D("a",{href:z.actionUrl,className:"min-w-0 flex-1",onClick:M,children:Q}):D("button",{type:"button",className:"min-w-0 flex-1",onClick:M,children:Q}),K&&G.onMarkRead?D(Z,{variant:"ghost",size:"icon",ariaLabelI18n:`Mark ${String(z.title)} as read`,onPress:P,children:D(q,{className:"h-4 w-4"})}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as
|
|
1
|
+
import{jsx as z,jsxs as Q}from"react/jsx-runtime";import{Sidebar as L,SidebarContent as R,SidebarFooter as B,SidebarGroup as K,SidebarGroupContent as N,SidebarGroupLabel as C,SidebarHeader as G,SidebarMenu as Z,SidebarMenuBadge as I,SidebarMenuButton as P,SidebarMenuItem as T,SidebarProvider as M,SidebarRail as p}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as $}from"@contractspec/lib.ui-kit-web/ui/utils";function g(q,D){if(q.active)return!0;if(!D||!q.href)return!1;return q.match==="startsWith"?D.startsWith(q.href):D===q.href}function k(q){return q.key??q.href??String(q.label)}function A({item:q,activeHref:D,depth:J=0}){const U=g(q,D),E=q.disabled||q.policyDecision?.effect==="deny",X=Boolean(q.children?.length),V=Q("span",{className:$("inline-flex min-w-0 items-center gap-2",J>0&&"pl-4"),children:[q.icon,z("span",{className:"truncate",children:q.label})]});return Q(T,{children:[z(P,{asChild:!!q.href&&!E,isActive:U,"aria-disabled":E,"aria-label":q.href&&!E?void 0:q.ariaLabel,disabled:E,onClick:q.href||E?void 0:()=>q.onSelect?.(),children:q.href&&!E?z("a",{href:q.href,target:q.target,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),children:V}):V}),q.badge!=null&&z(I,{children:q.badge}),X&&z(Z,{className:"mt-1",children:q.children?.map((O)=>z(A,{item:O,activeHref:D,depth:J+1},k(O)))})]})}export function ShellSidebar({sections:q,brand:D,commandTrigger:J,footer:U,activeHref:E,className:X,withProvider:V=!0}){const O=Q(L,{className:X,children:[z(p,{}),Q(G,{className:$("gap-3",!D&&!J&&"hidden"),children:[D,J]}),z(R,{children:q.map((W,F)=>Q(K,{children:[W.title&&z(C,{children:W.title}),z(N,{children:z(Z,{children:W.items.map((Y)=>z(A,{item:Y,activeHref:E},k(Y)))})})]},W.key??F))}),U&&z(B,{children:U})]});return V?z(M,{children:O}):O}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as
|
|
1
|
+
import{jsx as z,jsxs as k}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{Select as Q}from"../../components/forms/controls/Select";import{HStack as U}from"../../components/layout/Stack";import{optionValue as W}from"../../components/primitives/control";import{useTranslatedText as Y}from"../../components/primitives/themed";import{countryCallingCode as Z,countryFlag as $}from"./phone-country-utils";import{FORM_FALLBACK_TEXT as J}from"./values";export function PhoneFlag(b){if(b.hidden)return null;const q=$(b.iso2);if(!q)return null;return z("span",{"aria-label":b.iso2,className:"shrink-0 text-lg",role:"img",children:q})}export function PhoneCountryControl(b){const q=Y(),D=b.display.countrySelect;return k(U,{align:"center",gap:"sm",children:[z(PhoneFlag,{iso2:b.countryIso2,hidden:D||!b.display.flag}),D?z(Q,{id:b.id,name:b.name,value:b.selectValue,onChange:(G)=>b.onCountryChange(W(G)),options:b.selectOptions,disabled:b.disabled||b.readOnly}):z(N,{id:b.id,name:b.name,value:b.countryCode,onChange:(G)=>b.onCountryChange(G.currentTarget.value),placeholder:q(b.parts?.placeholdersI18n?.countryCode??J.countryCode),"aria-label":q(J.countryCode),readOnly:b.readOnly,disabled:b.disabled}),!D&&b.display.callingCode?z("span",{className:"min-w-12 text-muted-foreground text-sm",children:Z(b.countryIso2)||b.countryCode}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as q,jsxs as
|
|
1
|
+
import{jsx as q,jsxs as I}from"react/jsx-runtime";import{Input as Q}from"../../components/atoms/Input";import{Select as U}from"../../components/forms/controls/Select";import{HStack as W}from"../../components/layout/Stack";import{inputValue as Y,optionValue as Z}from"../../components/primitives/control";import{useTranslatedText as $}from"../../components/primitives/themed";import{Text as J}from"../../components/typography/Typography";import{countryCallingCode as k,countryFlag as H}from"./phone-country-utils";import{FORM_FALLBACK_TEXT as N}from"./values";export function PhoneFlag(b){if(b.hidden)return null;const z=H(b.iso2);if(!z)return null;return q(J,{className:"shrink-0 text-lg",children:z})}export function PhoneCountryControl(b){const z=$(),D=b.display.countrySelect;return I(W,{align:"center",gap:"sm",children:[q(PhoneFlag,{iso2:b.countryIso2,hidden:D||!b.display.flag}),D?q(U,{value:b.selectValue,onChange:(G)=>b.onCountryChange(Z(G)),options:b.selectOptions,disabled:b.disabled||b.readOnly}):q(Q,{value:b.countryCode,onChange:(G)=>b.onCountryChange(Y(G)),placeholder:z(b.parts?.placeholdersI18n?.countryCode??N.countryCode),ariaLabelI18n:N.countryCode,readOnly:b.readOnly,disabled:b.disabled}),!D&&b.display.callingCode?q(J,{className:"min-w-12 text-muted-foreground text-sm",children:k(b.countryIso2)||b.countryCode}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"country-flag-icons/unicode";import{getCountries as a,getCountryCallingCode as u}from"libphonenumber-js/min";const c=a();export function normalizeIso2(e){const n=e?.trim().toUpperCase();return n&&c.includes(n)?n:void 0}export function countryCallingCode(e){const n=normalizeIso2(e);return n?`+${u(n)}`:""}export function countryFlag(e){const n=normalizeIso2(e);return n?s(n):""}function l(e){const n=e?.allowedIso2?.map((o)=>normalizeIso2(o)).filter((o)=>Boolean(o));return n?.length?n:c}export function isAllowedPhoneCountry(e,n){const o=normalizeIso2(e);return Boolean(o&&l(n).includes(o))}export function countryFromCallingCode(e,n,o){const t=e?.trim().replace(/^\+/,"");if(!t)return;const r=l(n),i=normalizeIso2(o);if(i&&r.includes(i)&&u(i)===t)return i;return r.find((d)=>u(d)===t)}export function countryFromInput(e,n,o){const t=e?.trim(),r=normalizeIso2(t);return(r&&isAllowedPhoneCountry(r,n)?r:void 0)??countryFromCallingCode(t,n,o)}export function phoneCountryOptions(e,n){return l(e).map((o)=>{const t=countryCallingCode(o);return{labelI18n:[n?.flag===!1?void 0:countryFlag(o),o,n?.callingCode===!1?void 0:t].filter((i)=>Boolean(i)).join(" "),value:o}})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as
|
|
1
|
+
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as H}from"./values";export const PhoneField=(b)=>{const Z=A(),X=b.input?.mode??"split",g=b.input?.autoSwitch??!0,k=b.country?.detection??"input",W=b.output?.countryCodeFormat,$={flag:b.display?.flag??!0,callingCode:b.display?.callingCode??!0,countrySelect:b.display?.countrySelect??!0,extension:b.display?.extension??!0},G=E(b.value,b.country,W),Y=G.countryIso2,B=b.countryOptions?.length?b.countryOptions:d(b.country,$),M=B.some((q)=>String(q.value).toUpperCase()===Y)?Y:G.countryCode,Q=(q)=>{b.onChange?.(E(q,b.country,W))},S=(q)=>{const J=C(q,b.country,Y);Q({...G,countryIso2:J,countryCode:W==="iso2"?J??q:j(J)||q,e164:void 0})},f=(q)=>{if(g&&k==="input"&&q.trim().startsWith("+")){Q(K(q,G,b.country,W));return}Q({...G,nationalNumber:q,e164:void 0})},P=G.e164||`${G.countryCode}${G.nationalNumber}`,O=U(L,{id:b.id?`${b.id}-country`:void 0,name:b.name?`${b.name}.countryCode`:void 0,countryCode:G.countryCode,countryIso2:Y,selectValue:M,selectOptions:B,parts:b.parts,display:$,disabled:b.disabled,readOnly:b.readOnly,onCountryChange:S});if(X==="single")return U(D,{gap:"sm",children:R(V,{align:"center",gap:"sm",children:[U(T,{iso2:Y,hidden:!$.flag}),U(N,{id:b.id,name:b.name,value:P,onChange:(q)=>{const J=z(q);if(g&&k==="input"&&J.trim().startsWith("+")){Q(K(J,G,b.country,W));return}Q({...G,nationalNumber:J,e164:void 0})},placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled})]})});return R(D,{gap:"sm",children:[O,U(N,{id:b.id,name:b.name,value:G.nationalNumber,onChange:(q)=>f(z(q)),placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel-national"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled}),$.extension?U(N,{id:b.id?`${b.id}-extension`:void 0,name:b.name?`${b.name}.extension`:void 0,value:G.extension??"",onChange:(q)=>Q({...G,extension:z(q)}),placeholder:Z(b.parts?.placeholdersI18n?.extension??H.extension),keyboard:{kind:"number"},"aria-label":Z(H.extension),readOnly:b.readOnly,disabled:b.disabled}):null]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as z,jsxs as
|
|
1
|
+
import{jsx as z,jsxs as k}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{Select as Q}from"../../components/forms/controls/Select";import{HStack as U}from"../../components/layout/Stack";import{optionValue as W}from"../../components/primitives/control";import{useTranslatedText as Y}from"../../components/primitives/themed";import{countryCallingCode as Z,countryFlag as $}from"./phone-country-utils";import{FORM_FALLBACK_TEXT as J}from"./values";export function PhoneFlag(b){if(b.hidden)return null;const q=$(b.iso2);if(!q)return null;return z("span",{"aria-label":b.iso2,className:"shrink-0 text-lg",role:"img",children:q})}export function PhoneCountryControl(b){const q=Y(),D=b.display.countrySelect;return k(U,{align:"center",gap:"sm",children:[z(PhoneFlag,{iso2:b.countryIso2,hidden:D||!b.display.flag}),D?z(Q,{id:b.id,name:b.name,value:b.selectValue,onChange:(G)=>b.onCountryChange(W(G)),options:b.selectOptions,disabled:b.disabled||b.readOnly}):z(N,{id:b.id,name:b.name,value:b.countryCode,onChange:(G)=>b.onCountryChange(G.currentTarget.value),placeholder:q(b.parts?.placeholdersI18n?.countryCode??J.countryCode),"aria-label":q(J.countryCode),readOnly:b.readOnly,disabled:b.disabled}),!D&&b.display.callingCode?z("span",{className:"min-w-12 text-muted-foreground text-sm",children:Z(b.countryIso2)||b.countryCode}):null]})}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FormOption, PhoneCountrySpec } from '@contractspec/lib.contracts-spec/forms';
|
|
1
|
+
import type { FormOption, PhoneCountrySpec, PhoneFieldSpec } from '@contractspec/lib.contracts-spec/forms';
|
|
2
2
|
import { type CountryCode } from 'libphonenumber-js/min';
|
|
3
3
|
export declare function normalizeIso2(value: string | undefined): CountryCode | undefined;
|
|
4
4
|
export declare function countryCallingCode(iso2: string | undefined): string;
|
|
@@ -6,4 +6,4 @@ export declare function countryFlag(iso2: string | undefined): string;
|
|
|
6
6
|
export declare function isAllowedPhoneCountry(value: string | undefined, country?: PhoneCountrySpec): boolean;
|
|
7
7
|
export declare function countryFromCallingCode(callingCode: string | undefined, country?: PhoneCountrySpec, preferredIso2?: string): CountryCode | undefined;
|
|
8
8
|
export declare function countryFromInput(value: string | undefined, country?: PhoneCountrySpec, preferredIso2?: string): CountryCode | undefined;
|
|
9
|
-
export declare function phoneCountryOptions(country?: PhoneCountrySpec): FormOption[];
|
|
9
|
+
export declare function phoneCountryOptions(country?: PhoneCountrySpec, display?: Pick<NonNullable<PhoneFieldSpec['display']>, 'flag' | 'callingCode'>): FormOption[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"country-flag-icons/unicode";import{getCountries as a,getCountryCallingCode as u}from"libphonenumber-js/min";const c=a();export function normalizeIso2(e){const n=e?.trim().toUpperCase();return n&&c.includes(n)?n:void 0}export function countryCallingCode(e){const n=normalizeIso2(e);return n?`+${u(n)}`:""}export function countryFlag(e){const n=normalizeIso2(e);return n?s(n):""}function l(e){const n=e?.allowedIso2?.map((o)=>normalizeIso2(o)).filter((o)=>Boolean(o));return n?.length?n:c}export function isAllowedPhoneCountry(e,n){const o=normalizeIso2(e);return Boolean(o&&l(n).includes(o))}export function countryFromCallingCode(e,n,o){const t=e?.trim().replace(/^\+/,"");if(!t)return;const r=l(n),i=normalizeIso2(o);if(i&&r.includes(i)&&u(i)===t)return i;return r.find((d)=>u(d)===t)}export function countryFromInput(e,n,o){const t=e?.trim(),r=normalizeIso2(t);return(r&&isAllowedPhoneCountry(r,n)?r:void 0)??countryFromCallingCode(t,n,o)}export function phoneCountryOptions(e,n){return l(e).map((o)=>{const t=countryCallingCode(o);return{labelI18n:[n?.flag===!1?void 0:countryFlag(o),o,n?.callingCode===!1?void 0:t].filter((i)=>Boolean(i)).join(" "),value:o}})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as
|
|
1
|
+
import{jsx as U,jsxs as R}from"react/jsx-runtime";import{Input as N}from"../../components/atoms/Input";import{HStack as V,VStack as D}from"../../components/layout/Stack";import{inputValue as z}from"../../components/primitives/control";import{useTranslatedText as A}from"../../components/primitives/themed";import{PhoneCountryControl as L,PhoneFlag as T}from"./phone-country-control";import{countryCallingCode as j,countryFromInput as C,phoneCountryOptions as d}from"./phone-country-utils";import{normalizePhoneForDisplay as E,parsePhoneInput as K}from"./phone-utils";import{FORM_FALLBACK_TEXT as H}from"./values";export const PhoneField=(b)=>{const Z=A(),X=b.input?.mode??"split",g=b.input?.autoSwitch??!0,k=b.country?.detection??"input",W=b.output?.countryCodeFormat,$={flag:b.display?.flag??!0,callingCode:b.display?.callingCode??!0,countrySelect:b.display?.countrySelect??!0,extension:b.display?.extension??!0},G=E(b.value,b.country,W),Y=G.countryIso2,B=b.countryOptions?.length?b.countryOptions:d(b.country,$),M=B.some((q)=>String(q.value).toUpperCase()===Y)?Y:G.countryCode,Q=(q)=>{b.onChange?.(E(q,b.country,W))},S=(q)=>{const J=C(q,b.country,Y);Q({...G,countryIso2:J,countryCode:W==="iso2"?J??q:j(J)||q,e164:void 0})},f=(q)=>{if(g&&k==="input"&&q.trim().startsWith("+")){Q(K(q,G,b.country,W));return}Q({...G,nationalNumber:q,e164:void 0})},P=G.e164||`${G.countryCode}${G.nationalNumber}`,O=U(L,{id:b.id?`${b.id}-country`:void 0,name:b.name?`${b.name}.countryCode`:void 0,countryCode:G.countryCode,countryIso2:Y,selectValue:M,selectOptions:B,parts:b.parts,display:$,disabled:b.disabled,readOnly:b.readOnly,onCountryChange:S});if(X==="single")return U(D,{gap:"sm",children:R(V,{align:"center",gap:"sm",children:[U(T,{iso2:Y,hidden:!$.flag}),U(N,{id:b.id,name:b.name,value:P,onChange:(q)=>{const J=z(q);if(g&&k==="input"&&J.trim().startsWith("+")){Q(K(J,G,b.country,W));return}Q({...G,nationalNumber:J,e164:void 0})},placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled})]})});return R(D,{gap:"sm",children:[O,U(N,{id:b.id,name:b.name,value:G.nationalNumber,onChange:(q)=>f(z(q)),placeholder:Z(b.parts?.placeholdersI18n?.nationalNumber??H.phoneNumber),keyboard:{kind:"phone",autoComplete:"tel-national"},"aria-invalid":b["aria-invalid"],"aria-describedby":b["aria-describedby"],readOnly:b.readOnly,disabled:b.disabled}),$.extension?U(N,{id:b.id?`${b.id}-extension`:void 0,name:b.name?`${b.name}.extension`:void 0,value:G.extension??"",onChange:(q)=>Q({...G,extension:z(q)}),placeholder:Z(b.parts?.placeholdersI18n?.extension??H.extension),keyboard:{kind:"number"},"aria-label":Z(H.extension),readOnly:b.readOnly,disabled:b.disabled}):null]})};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/lib.design-system",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.2",
|
|
4
4
|
"description": "Design tokens and theming primitives",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contractspec",
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
"sideEffects": false,
|
|
32
32
|
"tree-shake": true,
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@contractspec/lib.ai-agent": "8.0.
|
|
35
|
-
"@contractspec/lib.contracts-runtime-client-react": "3.14.
|
|
36
|
-
"@contractspec/lib.contracts-spec": "6.
|
|
37
|
-
"@contractspec/lib.presentation-runtime-core": "5.2.
|
|
38
|
-
"@contractspec/lib.presentation-runtime-react": "40.0.
|
|
34
|
+
"@contractspec/lib.ai-agent": "8.0.16",
|
|
35
|
+
"@contractspec/lib.contracts-runtime-client-react": "3.14.1",
|
|
36
|
+
"@contractspec/lib.contracts-spec": "6.3.0",
|
|
37
|
+
"@contractspec/lib.presentation-runtime-core": "5.2.2",
|
|
38
|
+
"@contractspec/lib.presentation-runtime-react": "40.0.2",
|
|
39
39
|
"@contractspec/lib.schema": "3.7.14",
|
|
40
|
-
"@contractspec/lib.translation-runtime": "0.2.
|
|
41
|
-
"@contractspec/lib.ui-kit": "4.1.
|
|
42
|
-
"@contractspec/lib.ui-kit-core": "3.8.
|
|
43
|
-
"@contractspec/lib.ui-kit-web": "3.13.
|
|
40
|
+
"@contractspec/lib.translation-runtime": "0.2.1",
|
|
41
|
+
"@contractspec/lib.ui-kit": "4.1.5",
|
|
42
|
+
"@contractspec/lib.ui-kit-core": "3.8.8",
|
|
43
|
+
"@contractspec/lib.ui-kit-web": "3.13.3",
|
|
44
44
|
"@hookform/resolvers": "5.2.2",
|
|
45
45
|
"class-variance-authority": "^0.7.1",
|
|
46
46
|
"clsx": "^2.1.1",
|