@hollis-labs/kit-admin 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/LICENSE +21 -0
- package/README.md +169 -2
- package/dist/activity-dialog.js +42 -0
- package/dist/activity-dialog.js.map +1 -0
- package/dist/activity-directory.js +63 -0
- package/dist/activity-directory.js.map +1 -0
- package/dist/activity-history.js +44 -0
- package/dist/activity-history.js.map +1 -0
- package/dist/admin.js +160 -0
- package/dist/admin.js.map +1 -0
- package/dist/charts.js +9 -0
- package/dist/charts.js.map +1 -0
- package/dist/directory.js +42 -0
- package/dist/directory.js.map +1 -0
- package/dist/editor.js +71 -0
- package/dist/editor.js.map +1 -0
- package/dist/identity-avatar.js +23 -0
- package/dist/identity-avatar.js.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/model.js +24 -0
- package/dist/model.js.map +1 -0
- package/dist/src/activity-dialog.d.ts +32 -0
- package/dist/src/activity-directory.d.ts +40 -0
- package/dist/src/activity-history.d.ts +18 -0
- package/dist/src/admin.d.ts +7 -0
- package/dist/src/charts.d.ts +3 -0
- package/dist/src/directory.d.ts +27 -0
- package/dist/src/editor.d.ts +48 -0
- package/dist/src/identity-avatar.d.ts +4 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/model.d.ts +4 -0
- package/dist/src/types.d.ts +93 -0
- package/package.json +94 -4
- package/src/styles/source.css +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sources":["../src/admin.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { Activity, LayoutDashboard, Settings, SquareTerminal } from 'lucide-react'\nimport { AppShell, Button, Callout } from '@hollis-labs/design-components'\nimport { NavRail, PageHeader } from '@hollis-labs/kit-dashboard/ui'\nimport { ListPageLayout } from '@hollis-labs/kit-dashboard/layout'\nimport { SettingsProvenanceRenderer, SettingsWizard, settingsMetadataProblem } from '@hollis-labs/kit-settings'\nimport { DiagnosticPanel, HealthSummary, ObservationStatus, StatCollection } from '@hollis-labs/kit-observe'\nimport type { ObservationState } from '@hollis-labs/kit-observe'\nimport { adminManifestProblem, adminPages } from './model'\nimport type { AdminContentProps, AdminDestination, AdminManifest, AdminPage, AdminSettingsRead } from './types'\n\nconst labels = { dashboard: 'Dashboard', settings: 'Settings', status: 'Status', diagnostics: 'Diagnostics' } as const\nconst icons = { dashboard: LayoutDashboard, settings: Settings, status: Activity, diagnostics: SquareTerminal }\nfunction available(props: AdminContentProps): AdminManifest | undefined {\n const { discovery, contextKey } = props\n if (discovery.contextKey !== contextKey || adminManifestProblem(discovery.manifest)) return undefined\n return discovery.manifest\n}\nfunction Destination({ destination, children }: { destination: AdminDestination; children: ReactNode }) {\n return destination.href !== undefined\n ? <a className=\"break-words text-control text-primary underline underline-offset-2 focus-visible:outline-ring\" href={destination.href}>{children}</a>\n : <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={destination.onSelect}>{children}</Button>\n}\nfunction Notice({ children }: { children: ReactNode }) {\n return <p role=\"status\" className=\"text-control text-fg-secondary\">{children}</p>\n}\nfunction GroupLinks({ manifest, props }: { manifest: AdminManifest; props: AdminContentProps }) {\n return <nav aria-label=\"Settings groups\" className=\"flex flex-wrap gap-3\">{manifest.settings.map(group => <Destination key={group.id} destination={props.destination({ page: 'settings', groupId: group.id })}>{group.label}</Destination>)}</nav>\n}\n\n/** Navigation is only a projection of declared sections; the host owns routing/history. */\nexport function AdminNavigation(props: AdminContentProps) {\n const manifest = available(props)\n const pages: readonly AdminPage[] = manifest ? adminPages(manifest) : ['dashboard']\n return <NavRail logoLabel={manifest?.app.label ?? 'Admin'} items={pages.map(page => {\n const Icon = icons[page]\n return { key: page, label: labels[page], icon: <Icon className=\"size-4\" aria-hidden />, active: props.selection.page === page, ...props.destination({ page }) }\n })} />\n}\n\nfunction SettingsPage({ props, manifest }: { props: AdminContentProps; manifest: AdminManifest }) {\n const { selection, settings = {}, settingsActions: actions, setup } = props\n const contextReady = props.discovery.phase === 'ready'\n const readReady = (read: AdminSettingsRead | undefined) => contextReady && read?.phase === 'ready' && !!read.state\n const selected = manifest.settings.find(group => group.id === selection.groupId)\n const states = Object.fromEntries(manifest.settings.map(group => [group.id, settings[group.id]?.state]))\n const change: NonNullable<AdminContentProps['settingsActions']>['onDraftChange'] = (id, draft) => { if (readReady(settings[id])) actions?.onDraftChange(id, draft) }\n const normal = selection.mode !== 'setup'\n let presentedGroup = selected, presentedStates = states\n const state = selected && states[selected.id]\n // Limit only this view; validate the host inputs before copying so malformed\n // permissions/provenance stay unavailable rather than being repaired here.\n if (normal && !actions && selected && state && !settingsMetadataProblem(selected, state)) {\n presentedGroup = { ...selected, capabilities: {\n ...(selected.capabilities as Record<string, unknown>), can_validate: false, can_update: false, can_reset: false,\n } }\n presentedStates = { ...states, [selected.id]: { ...state, draft: {}, values: Object.fromEntries(\n Object.entries(state.values).map(([key, value]) => [key, value.editable\n ? { ...value, editable: false, read_only_reason: 'This view has no editing actions.' } : value]),\n ) } }\n }\n if (!manifest.settings.length) return <Notice>Settings unsupported: no settings groups declared.</Notice>\n return <section aria-label=\"Admin Settings\" className=\"flex min-w-0 flex-col gap-4\">\n <GroupLinks manifest={manifest} props={props} />\n {normal && selected?.scope ? <Notice>Scope: {selected.scope.kind}{selected.scope.id ? ` / ${selected.scope.id}` : ''}</Notice> : null}\n {normal ? !selection.groupId ? <Notice>Choose a settings group.</Notice> : !selected ? <Callout tone=\"warning\" title=\"Settings group unavailable\">This declaration does not contain the selected group.</Callout> : <>\n {settings[selected.id]?.phase === 'error' ? <Callout tone=\"danger\" title=\"Settings read failed\">{settings[selected.id]?.error ?? 'The host could not read this group.'} {settings[selected.id]?.state ? 'Previous snapshot retained; writes suspended.' : 'No successful snapshot is available.'}</Callout> : null}\n {settings[selected.id]?.phase === 'loading' ? <Notice>{settings[selected.id]?.state ? 'Refreshing settings snapshot; writes suspended.' : 'Waiting for a settings snapshot.'}</Notice> : null}\n <fieldset disabled={!readReady(settings[selected.id]) || !actions} className=\"min-w-0 border-0 p-0\">\n <SettingsProvenanceRenderer key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}:${selected.id}`}\n contractVersion={manifest.contract_version} groups={[presentedGroup!]} states={presentedStates} onDraftChange={change} readOnlyContext={!actions}\n onSave={readReady(settings[selected.id]) && actions?.onSave ? actions.onSave : undefined}\n onReset={readReady(settings[selected.id]) && actions?.onReset ? actions.onReset : undefined}\n onValidate={readReady(settings[selected.id]) && actions?.onValidate ? actions.onValidate : undefined}\n onApply={readReady(settings[selected.id]) && actions?.onApply ? actions.onApply : undefined} />\n </fieldset>\n </> : !setup ? <Notice>Setup unavailable: the host has not supplied setup controls.</Notice> : <>\n <Notice>Setup edits the same Settings groups. Source, locks and pending application remain in canonical Settings.</Notice>\n {props.setupContext}\n {manifest.settings.some(group => !readReady(settings[group.id]) || (states[group.id] && settingsMetadataProblem(group, states[group.id]!))) ? <Callout tone=\"warning\" title=\"Setup unavailable\">Every setup group needs a current, supported settings snapshot and provenance. Normal Settings remains available per group.</Callout> : <fieldset disabled={!contextReady || !actions} className=\"min-w-0 border-0 p-0\">\n <SettingsWizard key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}:setup`} {...setup}\n contractVersion={manifest.contract_version} groups={manifest.settings} states={states} onDraftChange={change}\n busy={!contextReady || !actions || setup.busy}\n onComplete={plan => { if (contextReady && actions) setup.onComplete(plan) }}\n onCheck={setup.onCheck ? id => { if (contextReady && actions) setup.onCheck?.(id) } : undefined} />\n </fieldset>}\n </>}\n </section>\n}\n\n/** Inner region for an existing host shell; no viewport wrapper, effects or local data store. */\nexport function AdminContent(props: AdminContentProps) {\n const { discovery, selection, observations = {}, nowMs } = props\n if (discovery.contextKey !== props.contextKey) return <Callout tone=\"warning\" title=\"Admin context unavailable\">The host must supply discovery and snapshots for the current authorized context.</Callout>\n if (!discovery.manifest) return discovery.phase === 'loading' ? <Notice>Loading admin declarations.</Notice> : <Callout tone=\"danger\" title=\"Admin unavailable\">{discovery.error ?? 'No admin declaration is available.'}</Callout>\n const problem = adminManifestProblem(discovery.manifest)\n if (problem) return <Callout tone=\"danger\" title=\"Admin declaration unavailable\">{problem}</Callout>\n const manifest = discovery.manifest\n const observation = (staleAfterMs: number): ObservationState => ({ phase: 'idle', nowMs, staleAfterMs })\n const pages = adminPages(manifest)\n let content: ReactNode\n if (selection.page === 'dashboard') content = <section aria-label=\"Admin directory\" className=\"flex min-w-0 flex-col gap-4\">\n <h2 className=\"text-heading text-fg\">{manifest.app.label}</h2>\n <Notice>Declaration revision: {manifest.revision}</Notice>\n {pages.length === 1 ? <Notice>No admin resources declared</Notice> : <nav aria-label=\"Admin directory links\" className=\"flex flex-wrap gap-3\">{pages.filter(page => page !== 'dashboard').map(page => <Destination key={page} destination={props.destination({ page })}>{labels[page]}</Destination>)}</nav>}\n {manifest.settings.length ? <GroupLinks manifest={manifest} props={props} /> : null}\n </section>\n else if (selection.page === 'settings') content = <SettingsPage props={props} manifest={manifest} />\n else if (selection.page === 'status') content = !manifest.health.length && !manifest.stats.length ? <Notice>Status unsupported: no health or stats resources declared.</Notice> : <section aria-label=\"Admin Status\" className=\"flex min-w-0 flex-col gap-4\">\n {manifest.health.map(resource => {\n const state = observations.health?.[resource.id]\n return state ? <HealthSummary key={resource.id} {...state} label={resource.label} /> : <ObservationStatus key={resource.id} label={resource.label} observation={observation(resource.stale_after_ms)} />\n })}\n {manifest.stats.length ? <StatCollection label=\"Stats\" rows={manifest.stats.map(resource => {\n const state = observations.stats?.[resource.id]\n return { id: resource.id, label: resource.label, unit: resource.unit, kind: resource.kind, value: state?.value ?? null, observation: state?.observation ?? observation(resource.stale_after_ms) }\n })} /> : null}\n </section>\n else if (selection.page === 'diagnostics') content = !manifest.series.length && !manifest.diagnostics.length ? <Notice>Diagnostics unsupported: no series or diagnostic resources declared.</Notice> : <section aria-label=\"Admin Diagnostics\" className=\"flex min-w-0 flex-col gap-4\">\n {manifest.series.map(resource => {\n const state = observations.series?.[resource.id]\n return <section key={resource.id} className=\"min-w-0\">{!props.renderSeries ? <Callout tone=\"warning\" title=\"Series renderer unavailable\">{resource.label}: the host has not supplied a series renderer.</Callout> : !state ? <ObservationStatus label={resource.label} observation={observation(resource.stale_after_ms)} /> : props.renderSeries({ ...state, label: resource.label, unit: resource.unit, kind: resource.kind, bounds: { maxPoints: resource.max_points, maxWindowSeconds: resource.max_window_seconds } })}</section>\n })}\n {manifest.diagnostics.map(resource => {\n const state = observations.diagnostics?.[resource.id]\n return state ? <DiagnosticPanel key={resource.id} {...state} label={resource.label} schema={resource.schema} /> : <ObservationStatus key={resource.id} label={resource.label} observation={observation(resource.stale_after_ms)} />\n })}\n </section>\n else content = <Callout tone=\"warning\" title=\"Admin page unavailable\">The host selected an unsupported page.</Callout>\n return <div key={`${props.contextKey}:${manifest.app.id}:${manifest.revision}`} className=\"mx-auto flex w-full min-w-0 max-w-5xl flex-col gap-4 p-4 text-control text-fg\">\n {discovery.phase !== 'ready' ? <Callout tone=\"warning\" title=\"Previous declarations retained\">{discovery.error ?? 'Refreshing admin declarations.'} Content uses the last declaration; writes are suspended until discovery succeeds.</Callout> : null}\n {content}\n </div>\n}\n\n/** Standalone viewport composition. Use AdminContent inside an existing AppShell instead. */\nexport function AdminShell(props: AdminContentProps) {\n const manifest = available(props)\n return <AppShell nav={<AdminNavigation {...props} />}>\n <ListPageLayout header={<PageHeader title={`${manifest?.app.label ?? 'Admin'} / ${labels[props.selection.page] ?? 'Unavailable'}`} />}>\n <AdminContent {...props} />\n </ListPageLayout>\n </AppShell>\n}\n"],"names":["labels","icons","LayoutDashboard","Settings","Activity","SquareTerminal","available","props","discovery","contextKey","adminManifestProblem","Destination","destination","children","jsx","Button","Notice","GroupLinks","manifest","group","AdminNavigation","pages","adminPages","NavRail","page","Icon","SettingsPage","selection","settings","actions","setup","contextReady","readReady","read","selected","states","_a","change","id","draft","normal","presentedGroup","presentedStates","state","settingsMetadataProblem","key","value","jsxs","Fragment","Callout","_b","_c","_d","_e","SettingsProvenanceRenderer","SettingsWizard","plan","AdminContent","observations","nowMs","problem","observation","staleAfterMs","content","resource","HealthSummary","ObservationStatus","StatCollection","DiagnosticPanel","AdminShell","AppShell","ListPageLayout","PageHeader"],"mappings":";;;;;;;;AAWA,MAAMA,IAAS,EAAE,WAAW,aAAa,UAAU,YAAY,QAAQ,UAAU,aAAa,cAAA,GACxFC,IAAQ,EAAE,WAAWC,GAAiB,UAAUC,GAAU,QAAQC,GAAU,aAAaC,EAAA;AAC/F,SAASC,EAAUC,GAAqD;AACtE,QAAM,EAAE,WAAAC,GAAW,YAAAC,EAAA,IAAeF;AAClC,MAAI,EAAAC,EAAU,eAAeC,KAAcC,EAAqBF,EAAU,QAAQ;AAClF,WAAOA,EAAU;AACnB;AACA,SAASG,EAAY,EAAE,aAAAC,GAAa,UAAAC,KAAoE;AACtG,SAAOD,EAAY,SAAS,SACxB,gBAAAE,EAAC,OAAE,WAAU,iGAAgG,MAAMF,EAAY,MAAO,UAAAC,EAAA,CAAS,IAC/I,gBAAAC,EAACC,GAAA,EAAO,MAAK,UAAS,MAAK,MAAK,SAAQ,WAAU,SAASH,EAAY,UAAW,UAAAC,EAAA,CAAS;AACjG;AACA,SAASG,EAAO,EAAE,UAAAH,KAAqC;AACrD,2BAAQ,KAAA,EAAE,MAAK,UAAS,WAAU,kCAAkC,UAAAA,GAAS;AAC/E;AACA,SAASI,EAAW,EAAE,UAAAC,GAAU,OAAAX,KAAgE;AAC9F,SAAO,gBAAAO,EAAC,OAAA,EAAI,cAAW,mBAAkB,WAAU,wBAAwB,UAAAI,EAAS,SAAS,IAAI,CAAAC,MAAS,gBAAAL,EAACH,GAAA,EAA2B,aAAaJ,EAAM,YAAY,EAAE,MAAM,YAAY,SAASY,EAAM,GAAA,CAAI,GAAI,UAAAA,EAAM,MAAA,GAA1FA,EAAM,EAA0F,CAAc,GAAE;AAC9O;AAGO,SAASC,EAAgBb,GAA0B;AACxD,QAAMW,IAAWZ,EAAUC,CAAK,GAC1Bc,IAA8BH,IAAWI,EAAWJ,CAAQ,IAAI,CAAC,WAAW;AAClF,SAAO,gBAAAJ,EAACS,GAAA,EAAQ,YAAWL,KAAA,gBAAAA,EAAU,IAAI,UAAS,SAAS,OAAOG,EAAM,IAAI,CAAAG,MAAQ;AAClF,UAAMC,IAAOxB,EAAMuB,CAAI;AACvB,WAAO,EAAE,KAAKA,GAAM,OAAOxB,EAAOwB,CAAI,GAAG,MAAM,gBAAAV,EAACW,GAAA,EAAK,WAAU,UAAS,eAAW,IAAC,GAAI,QAAQlB,EAAM,UAAU,SAASiB,GAAM,GAAGjB,EAAM,YAAY,EAAE,MAAAiB,EAAA,CAAM,EAAA;AAAA,EAC9J,CAAC,EAAA,CAAG;AACN;AAEA,SAASE,EAAa,EAAE,OAAAnB,GAAO,UAAAW,KAAmE;;AAChG,QAAM,EAAE,WAAAS,GAAW,UAAAC,IAAW,CAAA,GAAI,iBAAiBC,GAAS,OAAAC,MAAUvB,GAChEwB,IAAexB,EAAM,UAAU,UAAU,SACzCyB,IAAY,CAACC,MAAwCF,MAAgBE,KAAA,gBAAAA,EAAM,WAAU,WAAW,CAAC,CAACA,EAAK,OACvGC,IAAWhB,EAAS,SAAS,KAAK,OAASC,EAAM,OAAOQ,EAAU,OAAO,GACzEQ,IAAS,OAAO,YAAYjB,EAAS,SAAS,IAAI,CAAAC,MAAA;;AAAS,YAACA,EAAM,KAAIiB,IAAAR,EAAST,EAAM,EAAE,MAAjB,gBAAAiB,EAAoB,KAAK;AAAA,GAAC,CAAC,GACjGC,IAA6E,CAACC,GAAIC,MAAU;AAAE,IAAIP,EAAUJ,EAASU,CAAE,CAAC,MAAGT,KAAA,QAAAA,EAAS,cAAcS,GAAIC;AAAA,EAAO,GAC7JC,IAASb,EAAU,SAAS;AAClC,MAAIc,IAAiBP,GAAUQ,IAAkBP;AACjD,QAAMQ,IAAQT,KAAYC,EAAOD,EAAS,EAAE;AAY5C,SATIM,KAAU,CAACX,KAAWK,KAAYS,KAAS,CAACC,EAAwBV,GAAUS,CAAK,MACrFF,IAAiB,EAAE,GAAGP,GAAU,cAAc;AAAA,IAC5C,GAAIA,EAAS;AAAA,IAA0C,cAAc;AAAA,IAAO,YAAY;AAAA,IAAO,WAAW;AAAA,EAAA,EAC5G,GACAQ,IAAkB,EAAE,GAAGP,GAAQ,CAACD,EAAS,EAAE,GAAG,EAAE,GAAGS,GAAO,OAAO,CAAA,GAAI,QAAQ,OAAO;AAAA,IAClF,OAAO,QAAQA,EAAM,MAAM,EAAE,IAAI,CAAC,CAACE,GAAKC,CAAK,MAAM,CAACD,GAAKC,EAAM,WAC3D,EAAE,GAAGA,GAAO,UAAU,IAAO,kBAAkB,oCAAA,IAAwCA,CAAK,CAAC;AAAA,EAAA,IACjG,IAEC5B,EAAS,SAAS,SAChB,gBAAA6B,EAAC,WAAA,EAAQ,cAAW,kBAAiB,WAAU,+BACpD,UAAA;AAAA,IAAA,gBAAAjC,EAACG,GAAA,EAAW,UAAAC,GAAoB,OAAAX,EAAA,CAAc;AAAA,IAC7CiC,MAAUN,KAAA,QAAAA,EAAU,SAAQ,gBAAAa,EAAC/B,GAAA,EAAO,UAAA;AAAA,MAAA;AAAA,MAAQkB,EAAS,MAAM;AAAA,MAAMA,EAAS,MAAM,KAAK,MAAMA,EAAS,MAAM,EAAE,KAAK;AAAA,IAAA,EAAA,CAAG,IAAY;AAAA,IAChIM,IAAUb,EAAU,UAAuDO,IAAwI,gBAAAa,EAAAC,GAAA,EACjN,UAAA;AAAA,QAAAZ,IAAAR,EAASM,EAAS,EAAE,MAApB,gBAAAE,EAAuB,WAAU,4BAAWa,GAAA,EAAQ,MAAK,UAAS,OAAM,wBAAwB,UAAA;AAAA,UAAAC,IAAAtB,EAASM,EAAS,EAAE,MAApB,gBAAAgB,EAAuB,UAAS;AAAA,QAAsC;AAAA,SAAEC,IAAAvB,EAASM,EAAS,EAAE,MAApB,QAAAiB,EAAuB,QAAQ,kDAAkD;AAAA,MAAA,EAAA,CAAuC,IAAa;AAAA,QAC7SC,IAAAxB,EAASM,EAAS,EAAE,MAApB,gBAAAkB,EAAuB,WAAU,YAAY,gBAAAtC,EAACE,GAAA,EAAQ,WAAAqC,IAAAzB,EAASM,EAAS,EAAE,MAApB,QAAAmB,EAAuB,QAAQ,oDAAoD,oCAAmC,IAAY;AAAA,MACzL,gBAAAvC,EAAC,YAAA,EAAS,UAAU,CAACkB,EAAUJ,EAASM,EAAS,EAAE,CAAC,KAAK,CAACL,GAAS,WAAU,wBAC3E,UAAA,gBAAAf;AAAA,QAACwC;AAAA,QAAA;AAAA,UACC,iBAAiBpC,EAAS;AAAA,UAAkB,QAAQ,CAACuB,CAAe;AAAA,UAAG,QAAQC;AAAA,UAAiB,eAAeL;AAAA,UAAQ,iBAAiB,CAACR;AAAA,UACzI,QAAQG,EAAUJ,EAASM,EAAS,EAAE,CAAC,MAAKL,KAAA,QAAAA,EAAS,UAASA,EAAQ,SAAS;AAAA,UAC/E,SAASG,EAAUJ,EAASM,EAAS,EAAE,CAAC,MAAKL,KAAA,QAAAA,EAAS,WAAUA,EAAQ,UAAU;AAAA,UAClF,YAAYG,EAAUJ,EAASM,EAAS,EAAE,CAAC,MAAKL,KAAA,QAAAA,EAAS,cAAaA,EAAQ,aAAa;AAAA,UAC3F,SAASG,EAAUJ,EAASM,EAAS,EAAE,CAAC,MAAKL,KAAA,QAAAA,EAAS,WAAUA,EAAQ,UAAU;AAAA,QAAA;AAAA,QALnD,GAAGtB,EAAM,UAAU,IAAIW,EAAS,IAAI,EAAE,IAAIA,EAAS,QAAQ,IAAIgB,EAAS,EAAE;AAAA,MAAA,EAKZ,CACjG;AAAA,IAAA,EAAA,CACF,IAXuF,gBAAApB,EAACmC,KAAQ,MAAK,WAAU,OAAM,8BAA6B,UAAA,wDAAA,CAAqD,IAAxK,gBAAAnC,EAACE,GAAA,EAAO,sCAAwB,IAWxDc,IAAwF,gBAAAiB,EAAAC,GAAA,EAC7F,UAAA;AAAA,MAAA,gBAAAlC,EAACE,KAAO,UAAA,4GAAA,CAAyG;AAAA,MAChHT,EAAM;AAAA,MACNW,EAAS,SAAS,KAAK,CAAAC,MAAS,CAACa,EAAUJ,EAAST,EAAM,EAAE,CAAC,KAAMgB,EAAOhB,EAAM,EAAE,KAAKyB,EAAwBzB,GAAOgB,EAAOhB,EAAM,EAAE,CAAE,CAAE,IAAI,gBAAAL,EAACmC,KAAQ,MAAK,WAAU,OAAM,qBAAoB,UAAA,+HAA2H,IAAa,gBAAAnC,EAAC,cAAS,UAAU,CAACiB,KAAgB,CAACF,GAAS,WAAU,wBAC/X,UAAA,gBAAAf;AAAA,QAACyC;AAAA,QAAA;AAAA,UAA0F,GAAGzB;AAAA,UAC5F,iBAAiBZ,EAAS;AAAA,UAAkB,QAAQA,EAAS;AAAA,UAAU,QAAAiB;AAAA,UAAgB,eAAeE;AAAA,UACtG,MAAM,CAACN,KAAgB,CAACF,KAAWC,EAAM;AAAA,UACzC,YAAY,CAAA0B,MAAQ;AAAE,YAAIzB,KAAgBF,KAASC,EAAM,WAAW0B,CAAI;AAAA,UAAE;AAAA,UAC1E,SAAS1B,EAAM,UAAU,CAAAQ,MAAM;;AAAE,YAAIP,KAAgBF,OAASO,IAAAN,EAAM,YAAN,QAAAM,EAAA,KAAAN,GAAgBQ;AAAA,UAAI,IAAI;AAAA,QAAA;AAAA,QAJnE,GAAG/B,EAAM,UAAU,IAAIW,EAAS,IAAI,EAAE,IAAIA,EAAS,QAAQ;AAAA,MAAA,EAImB,CACrG;AAAA,IAAA,EAAA,CACF,sBAVgBF,GAAA,EAAO,UAAA,+DAAA,CAA4D;AAAA,EAUnF,GACF,IA1BsC,gBAAAF,EAACE,KAAO,UAAA,sDAAkD;AA2BlG;AAGO,SAASyC,EAAalD,GAA0B;AACrD,QAAM,EAAE,WAAAC,GAAW,WAAAmB,GAAW,cAAA+B,IAAe,CAAA,GAAI,OAAAC,MAAUpD;AAC3D,MAAIC,EAAU,eAAeD,EAAM,WAAY,QAAO,gBAAAO,EAACmC,GAAA,EAAQ,MAAK,WAAU,OAAM,6BAA4B,UAAA,mFAAA,CAAgF;AAChM,MAAI,CAACzC,EAAU,iBAAiBA,EAAU,UAAU,YAAY,gBAAAM,EAACE,GAAA,EAAO,yCAA2B,IAAY,gBAAAF,EAACmC,KAAQ,MAAK,UAAS,OAAM,qBAAqB,UAAAzC,EAAU,SAAS,qCAAA,CAAqC;AACzN,QAAMoD,IAAUlD,EAAqBF,EAAU,QAAQ;AACvD,MAAIoD,UAAgB,gBAAA9C,EAACmC,GAAA,EAAQ,MAAK,UAAS,OAAM,iCAAiC,UAAAW,EAAA,CAAQ;AAC1F,QAAM1C,IAAWV,EAAU,UACrBqD,IAAc,CAACC,OAA4C,EAAE,OAAO,QAAQ,OAAAH,GAAO,cAAAG,MACnFzC,IAAQC,EAAWJ,CAAQ;AACjC,MAAI6C;AACJ,SAAIpC,EAAU,SAAS,cAAaoC,sBAAW,WAAA,EAAQ,cAAW,mBAAkB,WAAU,+BAC5F,UAAA;AAAA,IAAA,gBAAAjD,EAAC,MAAA,EAAG,WAAU,wBAAwB,UAAAI,EAAS,IAAI,OAAM;AAAA,sBACxDF,GAAA,EAAO,UAAA;AAAA,MAAA;AAAA,MAAuBE,EAAS;AAAA,IAAA,GAAS;AAAA,IAChDG,EAAM,WAAW,IAAI,gBAAAP,EAACE,KAAO,UAAA,8BAAA,CAA2B,IAAY,gBAAAF,EAAC,OAAA,EAAI,cAAW,yBAAwB,WAAU,wBAAwB,UAAAO,EAAM,OAAO,CAAAG,MAAQA,MAAS,WAAW,EAAE,IAAI,CAAAA,MAAQ,gBAAAV,EAACH,GAAA,EAAuB,aAAaJ,EAAM,YAAY,EAAE,MAAAiB,EAAA,CAAM,GAAI,UAAAxB,EAAOwB,CAAI,EAAA,GAA5DA,CAA8D,CAAc,GAAE;AAAA,IACrSN,EAAS,SAAS,2BAAUD,GAAA,EAAW,UAAAC,GAAoB,OAAAX,GAAc,IAAK;AAAA,EAAA,GACjF,IACSoB,EAAU,SAAS,iBAAsB,gBAAAb,EAACY,GAAA,EAAa,OAAAnB,GAAc,UAAAW,GAAoB,IACzFS,EAAU,SAAS,WAAUoC,IAAU,CAAC7C,EAAS,OAAO,UAAU,CAACA,EAAS,MAAM,SAAS,gBAAAJ,EAACE,KAAO,UAAA,6DAAA,CAA0D,sBAAa,WAAA,EAAQ,cAAW,gBAAe,WAAU,+BAC5N,UAAA;AAAA,IAAAE,EAAS,OAAO,IAAI,CAAA8C,MAAY;;AAC/B,YAAMrB,KAAQP,IAAAsB,EAAa,WAAb,gBAAAtB,EAAsB4B,EAAS;AAC7C,aAAOrB,sBAASsB,GAAA,EAAiC,GAAGtB,GAAO,OAAOqB,EAAS,SAAxCA,EAAS,EAAsC,sBAAME,GAAA,EAAoC,OAAOF,EAAS,OAAO,aAAaH,EAAYG,EAAS,cAAc,KAApFA,EAAS,EAA8E;AAAA,IACxM,CAAC;AAAA,IACA9C,EAAS,MAAM,SAAS,gBAAAJ,EAACqD,GAAA,EAAe,OAAM,SAAQ,MAAMjD,EAAS,MAAM,IAAI,CAAA8C,MAAY;;AAC1F,YAAMrB,KAAQP,IAAAsB,EAAa,UAAb,gBAAAtB,EAAqB4B,EAAS;AAC5C,aAAO,EAAE,IAAIA,EAAS,IAAI,OAAOA,EAAS,OAAO,MAAMA,EAAS,MAAM,MAAMA,EAAS,MAAM,QAAOrB,KAAA,gBAAAA,EAAO,UAAS,MAAM,cAAaA,KAAA,gBAAAA,EAAO,gBAAekB,EAAYG,EAAS,cAAc,EAAA;AAAA,IAChM,CAAC,GAAG,IAAK;AAAA,EAAA,GACX,IACSrC,EAAU,SAAS,gBAAeoC,IAAU,CAAC7C,EAAS,OAAO,UAAU,CAACA,EAAS,YAAY,SAAS,gBAAAJ,EAACE,KAAO,UAAA,uEAAA,CAAoE,sBAAa,WAAA,EAAQ,cAAW,qBAAoB,WAAU,+BACtP,UAAA;AAAA,IAAAE,EAAS,OAAO,IAAI,CAAA8C,MAAY;;AAC/B,YAAMrB,KAAQP,IAAAsB,EAAa,WAAb,gBAAAtB,EAAsB4B,EAAS;AAC7C,aAAO,gBAAAlD,EAAC,WAAA,EAA0B,WAAU,WAAW,UAACP,EAAM,eAAuJoC,IAA0GpC,EAAM,aAAa,EAAE,GAAGoC,GAAO,OAAOqB,EAAS,OAAO,MAAMA,EAAS,MAAM,MAAMA,EAAS,MAAM,QAAQ,EAAE,WAAWA,EAAS,YAAY,kBAAkBA,EAAS,mBAAA,GAAsB,sBAA5RE,GAAA,EAAkB,OAAOF,EAAS,OAAO,aAAaH,EAAYG,EAAS,cAAc,GAAG,IAA7O,gBAAAjB,EAACE,GAAA,EAAQ,MAAK,WAAU,OAAM,+BAA+B,UAAA;AAAA,QAAAe,EAAS;AAAA,QAAM;AAAA,MAAA,GAA8C,EAAmT,GAAreA,EAAS,EAA8d;AAAA,IAC9f,CAAC;AAAA,IACA9C,EAAS,YAAY,IAAI,CAAA8C,MAAY;;AACpC,YAAMrB,KAAQP,IAAAsB,EAAa,gBAAb,gBAAAtB,EAA2B4B,EAAS;AAClD,aAAOrB,IAAQ,gBAAA7B,EAACsD,GAAA,EAAmC,GAAGzB,GAAO,OAAOqB,EAAS,OAAO,QAAQA,EAAS,OAAA,GAAhEA,EAAS,EAA+D,IAAK,gBAAAlD,EAACoD,GAAA,EAAoC,OAAOF,EAAS,OAAO,aAAaH,EAAYG,EAAS,cAAc,EAAA,GAApFA,EAAS,EAA8E;AAAA,IACnO,CAAC;AAAA,EAAA,GACH,QACe,gBAAAlD,EAACmC,GAAA,EAAQ,MAAK,WAAU,OAAM,0BAAyB,UAAA,0CAAsC,GACrG,gBAAAF,EAAC,OAAA,EAAwE,WAAU,iFACvF,UAAA;AAAA,IAAAvC,EAAU,UAAU,UAAU,gBAAAuC,EAACE,KAAQ,MAAK,WAAU,OAAM,kCAAkC,UAAA;AAAA,MAAAzC,EAAU,SAAS;AAAA,MAAiC;AAAA,IAAA,EAAA,CAAkF,IAAa;AAAA,IACjPuD;AAAA,EAAA,EAAA,GAFc,GAAGxD,EAAM,UAAU,IAAIW,EAAS,IAAI,EAAE,IAAIA,EAAS,QAAQ,EAG5E;AACF;AAGO,SAASmD,GAAW9D,GAA0B;AACnD,QAAMW,IAAWZ,EAAUC,CAAK;AAChC,SAAO,gBAAAO,EAACwD,GAAA,EAAS,KAAK,gBAAAxD,EAACM,KAAiB,GAAGb,EAAA,CAAO,GAChD,UAAA,gBAAAO,EAACyD,GAAA,EAAe,QAAQ,gBAAAzD,EAAC0D,GAAA,EAAW,OAAO,IAAGtD,KAAA,gBAAAA,EAAU,IAAI,UAAS,OAAO,MAAMlB,EAAOO,EAAM,UAAU,IAAI,KAAK,aAAa,GAAA,CAAI,GACjI,UAAA,gBAAAO,EAAC2C,GAAA,EAAc,GAAGlD,EAAA,CAAO,GAC3B,GACF;AACF;"}
|
package/dist/charts.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.js","sources":["../src/charts.tsx"],"sourcesContent":["import { SampleSeriesView, type SampleSeriesViewProps } from '@hollis-labs/kit-observe/charts'\n\n/** Supply to AdminContent/AdminShell renderSeries. The root never imports this module. */\nexport function renderAdminSeries(props: SampleSeriesViewProps) {\n return <SampleSeriesView {...props} />\n}\n"],"names":["renderAdminSeries","props","jsx","SampleSeriesView"],"mappings":";;AAGO,SAASA,EAAkBC,GAA8B;AAC9D,SAAO,gBAAAC,EAACC,GAAA,EAAkB,GAAGF,EAAA,CAAO;AACtC;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsxs as s, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { cn as i } from "@hollis-labs/design-components";
|
|
3
|
+
function p({ label: a, records: r, detail: l, controls: c, layout: n = "balanced" }) {
|
|
4
|
+
return /* @__PURE__ */ s("section", { "aria-label": a, className: "min-w-0", children: [
|
|
5
|
+
c,
|
|
6
|
+
/* @__PURE__ */ s("div", { className: i("min-w-0", n === "balanced" ? "grid lg:grid-cols-3" : "flex flex-col lg:flex-row"), children: [
|
|
7
|
+
/* @__PURE__ */ e("div", { className: i("min-w-0 max-h-80 overflow-y-auto border-b border-border lg:max-h-none lg:border-b-0 lg:border-r", n === "wide" && "lg:w-104 lg:shrink-0", n === "compact" && "lg:w-84 lg:shrink-0"), children: r }),
|
|
8
|
+
/* @__PURE__ */ e("div", { className: i("min-w-0", n === "balanced" ? "lg:col-span-2" : "flex-1"), children: l })
|
|
9
|
+
] })
|
|
10
|
+
] });
|
|
11
|
+
}
|
|
12
|
+
function b({ title: a, description: r, avatar: l, badge: c, selected: n, onSelect: d, muted: o = !1 }) {
|
|
13
|
+
return /* @__PURE__ */ s(
|
|
14
|
+
"button",
|
|
15
|
+
{
|
|
16
|
+
type: "button",
|
|
17
|
+
"aria-current": n ? "true" : void 0,
|
|
18
|
+
onClick: d,
|
|
19
|
+
className: i("flex w-full items-center gap-3 border-b border-border px-4 py-3 text-left transition-colors hover:bg-panel-2 focus-visible:bg-panel-2 focus-visible:outline-none", n && "bg-panel-2", o && "opacity-60"),
|
|
20
|
+
children: [
|
|
21
|
+
l && /* @__PURE__ */ e("span", { className: "shrink-0", children: l }),
|
|
22
|
+
/* @__PURE__ */ s("span", { className: "min-w-0 flex-1", children: [
|
|
23
|
+
/* @__PURE__ */ e("span", { className: "block break-words dash-record-title text-fg", children: a }),
|
|
24
|
+
r && /* @__PURE__ */ e("span", { className: "block break-words dash-record-metadata text-fg-muted", children: r })
|
|
25
|
+
] }),
|
|
26
|
+
c && /* @__PURE__ */ e("span", { className: "shrink-0 dash-support", children: c })
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
function h({ items: a }) {
|
|
32
|
+
return /* @__PURE__ */ e("dl", { className: "grid grid-cols-1 min-w-0 gap-x-4 gap-y-2 dash-support sm:grid-cols-3", children: a.map(({ label: r, value: l }) => /* @__PURE__ */ s("div", { className: "contents", children: [
|
|
33
|
+
/* @__PURE__ */ e("dt", { className: "text-fg-faint", children: r }),
|
|
34
|
+
/* @__PURE__ */ e("dd", { className: "min-w-0 break-words sm:col-span-2", children: l ?? "Not captured" })
|
|
35
|
+
] }, r)) });
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
p as AdminDirectory,
|
|
39
|
+
h as AdminFacts,
|
|
40
|
+
b as AdminRecordButton
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=directory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory.js","sources":["../src/directory.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { cn } from '@hollis-labs/design-components'\n\n/** Controlled record directory. The app owns filtering, selection, drafts and commands. */\nexport function AdminDirectory({ label, records, detail, controls, layout = 'balanced' }: { label: string; records: ReactNode; detail: ReactNode; controls?: ReactNode; layout?: 'balanced' | 'wide' | 'compact' }) {\n return <section aria-label={label} className=\"min-w-0\">\n {controls}\n <div className={cn('min-w-0', layout === 'balanced' ? 'grid lg:grid-cols-3' : 'flex flex-col lg:flex-row')}>\n <div className={cn('min-w-0 max-h-80 overflow-y-auto border-b border-border lg:max-h-none lg:border-b-0 lg:border-r', layout === 'wide' && 'lg:w-104 lg:shrink-0', layout === 'compact' && 'lg:w-84 lg:shrink-0')}>{records}</div>\n <div className={cn('min-w-0', layout === 'balanced' ? 'lg:col-span-2' : 'flex-1')}>{detail}</div>\n </div>\n </section>\n}\n\n/** One selectable directory row with shared type, spacing and selected/keyboard feedback. */\nexport function AdminRecordButton({ title, description, avatar, badge, selected, onSelect, muted = false }: {\n title: ReactNode; description?: ReactNode; avatar?: ReactNode; badge?: ReactNode; selected: boolean; onSelect: () => void; muted?: boolean; /** @deprecated Both legacy sizes now follow the dashboard typography profile. */ size?: 'default' | 'comfortable'\n}) {\n return <button type=\"button\" aria-current={selected ? 'true' : undefined} onClick={onSelect}\n className={cn('flex w-full items-center gap-3 border-b border-border px-4 py-3 text-left transition-colors hover:bg-panel-2 focus-visible:bg-panel-2 focus-visible:outline-none', selected && 'bg-panel-2', muted && 'opacity-60')}>\n {avatar && <span className=\"shrink-0\">{avatar}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block break-words dash-record-title text-fg\">{title}</span>\n {description && <span className=\"block break-words dash-record-metadata text-fg-muted\">{description}</span>}\n </span>\n {badge && <span className=\"shrink-0 dash-support\">{badge}</span>}\n </button>\n}\n\n/** Reusable metadata presentation; missing values stay explicit. */\nexport function AdminFacts({ items }: { items: { label: string; value: ReactNode }[] }) {\n return <dl className=\"grid grid-cols-1 min-w-0 gap-x-4 gap-y-2 dash-support sm:grid-cols-3\">\n {items.map(({label,value})=><div key={label} className=\"contents\"><dt className=\"text-fg-faint\">{label}</dt><dd className=\"min-w-0 break-words sm:col-span-2\">{value ?? 'Not captured'}</dd></div>)}\n </dl>\n}\n"],"names":["AdminDirectory","label","records","detail","controls","layout","jsxs","cn","jsx","AdminRecordButton","title","description","avatar","badge","selected","onSelect","muted","AdminFacts","items","value"],"mappings":";;AAIO,SAASA,EAAe,EAAE,OAAAC,GAAO,SAAAC,GAAS,QAAAC,GAAQ,UAAAC,GAAU,QAAAC,IAAS,cAAwI;AAClN,SAAO,gBAAAC,EAAC,WAAA,EAAQ,cAAYL,GAAO,WAAU,WAC1C,UAAA;AAAA,IAAAG;AAAA,IACD,gBAAAE,EAAC,SAAI,WAAWC,EAAG,WAAWF,MAAW,aAAa,wBAAwB,2BAA2B,GACvG,UAAA;AAAA,MAAA,gBAAAG,EAAC,OAAA,EAAI,WAAWD,EAAG,mGAAmGF,MAAW,UAAU,wBAAwBA,MAAW,aAAa,qBAAqB,GAAI,UAAAH,EAAA,CAAQ;AAAA,MAC5N,gBAAAM,EAAC,OAAA,EAAI,WAAWD,EAAG,WAAWF,MAAW,aAAa,kBAAkB,QAAQ,GAAI,UAAAF,EAAA,CAAO;AAAA,IAAA,EAAA,CAC7F;AAAA,EAAA,GACF;AACF;AAGO,SAASM,EAAkB,EAAE,OAAAC,GAAO,aAAAC,GAAa,QAAAC,GAAQ,OAAAC,GAAO,UAAAC,GAAU,UAAAC,GAAU,OAAAC,IAAQ,MAEhG;AACD,SAAO,gBAAAV;AAAA,IAAC;AAAA,IAAA;AAAA,MAAO,MAAK;AAAA,MAAS,gBAAcQ,IAAW,SAAS;AAAA,MAAW,SAASC;AAAA,MACjF,WAAWR,EAAG,oKAAoKO,KAAY,cAAcE,KAAS,YAAY;AAAA,MAChO,UAAA;AAAA,QAAAJ,KAAU,gBAAAJ,EAAC,QAAA,EAAK,WAAU,YAAY,UAAAI,GAAO;AAAA,QAC9C,gBAAAN,EAAC,QAAA,EAAK,WAAU,kBACd,UAAA;AAAA,UAAA,gBAAAE,EAAC,QAAA,EAAK,WAAU,+CAA+C,UAAAE,GAAM;AAAA,UACpEC,KAAe,gBAAAH,EAAC,QAAA,EAAK,WAAU,wDAAwD,UAAAG,EAAA,CAAY;AAAA,QAAA,GACtG;AAAA,QACCE,KAAS,gBAAAL,EAAC,QAAA,EAAK,WAAU,yBAAyB,UAAAK,EAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAE7D;AAGO,SAASI,EAAW,EAAE,OAAAC,KAA2D;AACtF,SAAO,gBAAAV,EAAC,MAAA,EAAG,WAAU,wEAClB,YAAM,IAAI,CAAC,EAAC,OAAAP,GAAM,OAAAkB,EAAA,MAAS,gBAAAb,EAAC,OAAA,EAAgB,WAAU,YAAW,UAAA;AAAA,IAAA,gBAAAE,EAAC,MAAA,EAAG,WAAU,iBAAiB,UAAAP,GAAM;AAAA,IAAK,gBAAAO,EAAC,MAAA,EAAG,WAAU,qCAAqC,eAAS,eAAA,CAAe;AAAA,EAAA,KAAjJP,CAAsJ,CAAM,GACpM;AACF;"}
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx as n, jsxs as d } from "react/jsx-runtime";
|
|
2
|
+
import { Button as s, cn as l, Input as m, Tabs as p, TabsList as f, TabsTrigger as b, Textarea as u } from "@hollis-labs/design-components";
|
|
3
|
+
function g({ children: e }) {
|
|
4
|
+
return /* @__PURE__ */ n("h3", { className: "mb-2 font-mono dash-caption uppercase tracking-widest text-fg-faint", children: e });
|
|
5
|
+
}
|
|
6
|
+
function w({ title: e, children: a }) {
|
|
7
|
+
return /* @__PURE__ */ d("section", { "aria-label": e, className: "min-w-0 border-b border-border px-5 py-4", children: [
|
|
8
|
+
/* @__PURE__ */ n(g, { children: e }),
|
|
9
|
+
a
|
|
10
|
+
] });
|
|
11
|
+
}
|
|
12
|
+
function N({ label: e, children: a }) {
|
|
13
|
+
return /* @__PURE__ */ d("div", { className: "flex flex-wrap gap-x-3 gap-y-1 py-0.5 dash-body", children: [
|
|
14
|
+
/* @__PURE__ */ n("dt", { className: "w-28 shrink-0 font-mono dash-label uppercase tracking-wider text-fg-faint", children: e }),
|
|
15
|
+
/* @__PURE__ */ n("dd", { className: "min-w-0 flex-1 basis-40 break-words text-fg", children: a })
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
function y({ className: e, ...a }) {
|
|
19
|
+
return /* @__PURE__ */ n("span", { ...a, className: l("inline-flex border border-border px-1.5 py-0.5 font-mono dash-label text-fg-muted", e) });
|
|
20
|
+
}
|
|
21
|
+
function A({ tone: e = "ghost", className: a, type: i = "button", ...t }) {
|
|
22
|
+
return /* @__PURE__ */ n(s, { ...t, type: i, variant: e === "primary" ? "default" : e === "danger" ? "destructive" : "outline", className: l("font-mono dash-label uppercase tracking-widest", a) });
|
|
23
|
+
}
|
|
24
|
+
function k({ label: e, value: a, onChange: i, items: t, actions: o }) {
|
|
25
|
+
return /* @__PURE__ */ d("div", { className: "flex min-w-0 flex-wrap items-center gap-2 border-b border-border px-4 py-1.5", children: [
|
|
26
|
+
/* @__PURE__ */ n(p, { value: a, onValueChange: (r) => i(r), children: /* @__PURE__ */ n(f, { "aria-label": e, className: "h-auto flex-wrap gap-1 bg-transparent p-0", children: t.map((r) => /* @__PURE__ */ n(
|
|
27
|
+
b,
|
|
28
|
+
{
|
|
29
|
+
value: r.key,
|
|
30
|
+
disabled: r.disabled,
|
|
31
|
+
title: r.title,
|
|
32
|
+
className: "h-auto px-2.5 py-1 font-mono dash-label font-normal uppercase tracking-widest data-active:bg-panel-2 data-active:text-fg",
|
|
33
|
+
children: r.label
|
|
34
|
+
},
|
|
35
|
+
r.key
|
|
36
|
+
)) }) }),
|
|
37
|
+
o && /* @__PURE__ */ n("div", { className: "ml-auto", children: o })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
function v({ label: e, htmlFor: a, changed: i, issues: t, children: o }) {
|
|
41
|
+
return /* @__PURE__ */ d("div", { className: l("min-w-0 border-l-2 py-1 pl-3", i ? "border-warning/70" : "border-transparent"), children: [
|
|
42
|
+
/* @__PURE__ */ d("label", { htmlFor: a, className: "mb-1 block font-mono dash-label uppercase tracking-wider text-fg-faint", children: [
|
|
43
|
+
e,
|
|
44
|
+
i && /* @__PURE__ */ n("span", { className: "ml-2 text-warning", children: "changed" })
|
|
45
|
+
] }),
|
|
46
|
+
o,
|
|
47
|
+
t == null ? void 0 : t.map((r, c) => /* @__PURE__ */ n("p", { className: l("mt-1 dash-support", r.level === "error" ? "text-danger" : "text-warning"), children: r.message }, c))
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
function T({ className: e, ...a }) {
|
|
51
|
+
return /* @__PURE__ */ n(m, { ...a, className: l("min-w-0 font-mono dash-control", e) });
|
|
52
|
+
}
|
|
53
|
+
function B({ className: e, ...a }) {
|
|
54
|
+
return /* @__PURE__ */ n("select", { ...a, className: l("w-full min-w-0", e) });
|
|
55
|
+
}
|
|
56
|
+
function j({ className: e, ...a }) {
|
|
57
|
+
return /* @__PURE__ */ n(u, { ...a, className: l("min-w-0 font-mono dash-control", e) });
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
A as AdminActionButton,
|
|
61
|
+
y as AdminBadge,
|
|
62
|
+
N as AdminFact,
|
|
63
|
+
v as AdminField,
|
|
64
|
+
g as AdminHeading,
|
|
65
|
+
T as AdminInput,
|
|
66
|
+
w as AdminSection,
|
|
67
|
+
B as AdminSelect,
|
|
68
|
+
k as AdminTabs,
|
|
69
|
+
j as AdminTextarea
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.js","sources":["../src/editor.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react'\nimport { Button, cn, Input, Tabs, TabsList, TabsTrigger, Textarea } from '@hollis-labs/design-components'\n\n/** Configuration section shared by inspectors, editors and review plans. */\nexport function AdminHeading({ children }: { children: ReactNode }) {\n return <h3 className=\"mb-2 font-mono dash-caption uppercase tracking-widest text-fg-faint\">{children}</h3>\n}\n\nexport function AdminSection({ title, children }: { title: string; children: ReactNode }) {\n return <section aria-label={title} className=\"min-w-0 border-b border-border px-5 py-4\">\n <AdminHeading>{title}</AdminHeading>{children}\n </section>\n}\n\n/** A semantic definition pair. Supply application-specific missing-value text. */\nexport function AdminFact({ label, children }: { label: string; children: ReactNode }) {\n return <div className=\"flex flex-wrap gap-x-3 gap-y-1 py-0.5 dash-body\">\n <dt className=\"w-28 shrink-0 font-mono dash-label uppercase tracking-wider text-fg-faint\">{label}</dt>\n <dd className=\"min-w-0 flex-1 basis-40 break-words text-fg\">{children}</dd>\n </div>\n}\n\nexport function AdminBadge({ className, ...props }: ComponentProps<'span'>) {\n return <span {...props} className={cn('inline-flex border border-border px-1.5 py-0.5 font-mono dash-label text-fg-muted', className)} />\n}\n\n/** Standard button behavior with the compact configuration idiom. */\nexport function AdminActionButton({ tone = 'ghost', className, type = 'button', ...props }: ComponentProps<'button'> & { tone?: 'primary' | 'danger' | 'ghost' }) {\n return <Button {...props} type={type} variant={tone === 'primary' ? 'default' : tone === 'danger' ? 'destructive' : 'outline'} className={cn('font-mono dash-label uppercase tracking-widest', className)} />\n}\n\n/** Controlled tabs: the base primitive owns arrow-key navigation and disabled tabs. */\nexport function AdminTabs<K extends string>({ label, value, onChange, items, actions }: {\n label: string; value: K; onChange: (value: K) => void;\n items: readonly { key: K; label: string; disabled?: boolean; title?: string }[]; actions?: ReactNode\n}) {\n return <div className=\"flex min-w-0 flex-wrap items-center gap-2 border-b border-border px-4 py-1.5\">\n <Tabs value={value} onValueChange={next => onChange(next as K)}>\n <TabsList aria-label={label} className=\"h-auto flex-wrap gap-1 bg-transparent p-0\">\n {items.map(item => <TabsTrigger key={item.key} value={item.key} disabled={item.disabled} title={item.title}\n className=\"h-auto px-2.5 py-1 font-mono dash-label font-normal uppercase tracking-widest data-active:bg-panel-2 data-active:text-fg\">{item.label}</TabsTrigger>)}\n </TabsList>\n </Tabs>\n {actions && <div className=\"ml-auto\">{actions}</div>}\n </div>\n}\n\n/** Validation remains host-owned; field presentation is shared. */\nexport function AdminField({ label, htmlFor, changed, issues, children }: {\n label: string; htmlFor?: string; changed?: boolean;\n issues?: readonly { level: string; message: string }[]; children: ReactNode\n}) {\n return <div className={cn('min-w-0 border-l-2 py-1 pl-3', changed ? 'border-warning/70' : 'border-transparent')}>\n <label htmlFor={htmlFor} className=\"mb-1 block font-mono dash-label uppercase tracking-wider text-fg-faint\">{label}{changed && <span className=\"ml-2 text-warning\">changed</span>}</label>\n {children}\n {issues?.map((issue, i) => <p key={i} className={cn('mt-1 dash-support', issue.level === 'error' ? 'text-danger' : 'text-warning')}>{issue.message}</p>)}\n </div>\n}\n\nexport function AdminInput({ className, ...props }: ComponentProps<typeof Input>) {\n return <Input {...props} className={cn('min-w-0 font-mono dash-control', className)} />\n}\n\n/** Native select preserves option/form semantics and uses dashboard control tokens. */\nexport function AdminSelect({ className, ...props }: ComponentProps<'select'>) {\n return <select {...props} className={cn('w-full min-w-0', className)} />\n}\n\nexport function AdminTextarea({ className, ...props }: ComponentProps<typeof Textarea>) {\n return <Textarea {...props} className={cn('min-w-0 font-mono dash-control', className)} />\n}\n"],"names":["AdminHeading","children","jsx","AdminSection","title","jsxs","AdminFact","label","AdminBadge","className","props","cn","AdminActionButton","tone","type","Button","AdminTabs","value","onChange","items","actions","Tabs","next","TabsList","item","TabsTrigger","AdminField","htmlFor","changed","issues","issue","i","AdminInput","Input","AdminSelect","AdminTextarea","Textarea"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsxs as d, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
function u(l) {
|
|
3
|
+
let a = 2166136261;
|
|
4
|
+
for (const e of l) a = Math.imul(a ^ e.charCodeAt(0), 16777619);
|
|
5
|
+
const i = ["text-status-doing", "text-status-done", "text-status-review", "text-status-blocked", "text-status-paused", "text-status-todo"], n = i[(a >>> 0) % i.length], s = () => (a = Math.imul(a, 1664525) + 1013904223 >>> 0, a / 4294967296), t = Array.from({ length: 8 }, () => Array(4).fill(!1));
|
|
6
|
+
t[0][3] = !0, s() > 0.5 && (t[0][0] = !0);
|
|
7
|
+
for (let e = 1; e <= 4; e++) for (let r = 1; r < 4; r++) t[e][r] = !0;
|
|
8
|
+
s() > 0.5 && (t[2][0] = t[3][0] = !0);
|
|
9
|
+
for (let e = 5; e < 8; e++)
|
|
10
|
+
t[e][3] = t[e][2] = !0, t[e][1] = s() > 0.35, t[e][0] = s() > 0.55;
|
|
11
|
+
return { tone: n, half: t };
|
|
12
|
+
}
|
|
13
|
+
function h({ identity: l, size: a = "default" }) {
|
|
14
|
+
const { tone: i, half: n } = u(l);
|
|
15
|
+
return /* @__PURE__ */ d("svg", { viewBox: "0 0 8 8", shapeRendering: "crispEdges", role: "img", "aria-label": "Robot identity", className: `${i} ${a === "small" ? "dash-identity-small" : a === "definition" ? "dash-identity-definition" : a === "detail" ? "size-18" : a === "large" ? "dash-identity-large" : "size-10"} shrink-0`, children: [
|
|
16
|
+
n.flatMap((s, t) => [...s, ...[...s].reverse()].map((e, r) => e && !(t === 2 && (r === 2 || r === 5)) ? /* @__PURE__ */ o("rect", { x: r, y: t, width: 1, height: 1, fill: "currentColor", opacity: t >= 5 ? 0.6 : 1 }, `${t}-${r}`) : null)),
|
|
17
|
+
/* @__PURE__ */ o("path", { d: "M2 2h1v1H2z M5 2h1v1H5z", className: "fill-bg" })
|
|
18
|
+
] });
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
h as IdentityAvatar
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=identity-avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-avatar.js","sources":["../src/identity-avatar.tsx"],"sourcesContent":["/** Deterministic robot identity harvested from Tachyon; color comes from the active theme. */\nfunction sprite(identity: string) {\n let seed = 2166136261\n for (const c of identity) seed = Math.imul(seed ^ c.charCodeAt(0), 16777619)\n const palette = ['text-status-doing','text-status-done','text-status-review','text-status-blocked','text-status-paused','text-status-todo']\n const tone = palette[(seed >>> 0) % palette.length]\n const next=()=>{seed=(Math.imul(seed,1664525)+1013904223)>>>0;return seed/0x100000000}\n const half:boolean[][]=Array.from({length:8},()=>Array(4).fill(false))\n half[0][3]=true;if(next()>.5)half[0][0]=true\n for(let r=1;r<=4;r++)for(let c=1;c<4;c++)half[r][c]=true\n if(next()>.5)half[2][0]=half[3][0]=true\n for(let r=5;r<8;r++){half[r][3]=half[r][2]=true;half[r][1]=next()>.35;half[r][0]=next()>.55}\n return {tone,half}\n}\n\nexport function IdentityAvatar({ identity, size = 'default' }: { identity: string; size?: 'small' | 'definition' | 'default' | 'large' | 'detail' }) {\n const {tone,half}=sprite(identity)\n return <svg viewBox=\"0 0 8 8\" shapeRendering=\"crispEdges\" role=\"img\" aria-label=\"Robot identity\" className={`${tone} ${size==='small'?'dash-identity-small':size==='definition'?'dash-identity-definition':size==='detail'?'size-18':size==='large'?'dash-identity-large':'size-10'} shrink-0`}>\n {half.flatMap((row,r)=>[...row,...[...row].reverse()].map((on,c)=>on&&!(r===2&&(c===2||c===5))?<rect key={`${r}-${c}`} x={c} y={r} width={1} height={1} fill=\"currentColor\" opacity={r>=5?.6:1}/>:null))}\n <path d=\"M2 2h1v1H2z M5 2h1v1H5z\" className=\"fill-bg\" />\n </svg>\n}\n"],"names":["sprite","identity","seed","c","palette","tone","next","half","r","IdentityAvatar","size","jsxs","row","on","jsx"],"mappings":";AACA,SAASA,EAAOC,GAAkB;AAChC,MAAIC,IAAO;AACX,aAAWC,KAAKF,EAAU,CAAAC,IAAO,KAAK,KAAKA,IAAOC,EAAE,WAAW,CAAC,GAAG,QAAQ;AAC3E,QAAMC,IAAU,CAAC,qBAAoB,oBAAmB,sBAAqB,uBAAsB,sBAAqB,kBAAkB,GACpIC,IAAOD,GAASF,MAAS,KAAKE,EAAQ,MAAM,GAC5CE,IAAK,OAAKJ,IAAM,KAAK,KAAKA,GAAK,OAAO,IAAE,eAAc,GAASA,IAAK,aACpEK,IAAiB,MAAM,KAAK,EAAC,QAAO,KAAG,MAAI,MAAM,CAAC,EAAE,KAAK,EAAK,CAAC;AACrE,EAAAA,EAAK,CAAC,EAAE,CAAC,IAAE,IAAQD,MAAO,UAAQ,CAAC,EAAE,CAAC,IAAE;AACxC,WAAQE,IAAE,GAAEA,KAAG,GAAEA,IAAI,UAAQL,IAAE,GAAEA,IAAE,GAAEA,IAAI,CAAAI,EAAKC,CAAC,EAAEL,CAAC,IAAE;AACpD,EAAGG,EAAA,IAAO,QAAGC,EAAK,CAAC,EAAE,CAAC,IAAEA,EAAK,CAAC,EAAE,CAAC,IAAE;AACnC,WAAQC,IAAE,GAAEA,IAAE,GAAEA;AAAK,IAAAD,EAAKC,CAAC,EAAE,CAAC,IAAED,EAAKC,CAAC,EAAE,CAAC,IAAE,IAAKD,EAAKC,CAAC,EAAE,CAAC,IAAEF,MAAO,MAAIC,EAAKC,CAAC,EAAE,CAAC,IAAEF,MAAO;AACxF,SAAO,EAAC,MAAAD,GAAK,MAAAE,EAAA;AACf;AAEO,SAASE,EAAe,EAAE,UAAAR,GAAU,MAAAS,IAAO,aAAmG;AACnJ,QAAM,EAAC,MAAAL,GAAK,MAAAE,MAAMP,EAAOC,CAAQ;AACjC,SAAO,gBAAAU,EAAC,OAAA,EAAI,SAAQ,WAAU,gBAAe,cAAa,MAAK,OAAM,cAAW,kBAAiB,WAAW,GAAGN,CAAI,IAAIK,MAAO,UAAQ,wBAAsBA,MAAO,eAAa,6BAA2BA,MAAO,WAAS,YAAUA,MAAO,UAAQ,wBAAsB,SAAS,aAChR,UAAA;AAAA,IAAAH,EAAK,QAAQ,CAACK,GAAIJ,MAAI,CAAC,GAAGI,GAAI,GAAG,CAAC,GAAGA,CAAG,EAAE,QAAA,CAAS,EAAE,IAAI,CAACC,GAAGV,MAAIU,KAAI,EAAEL,MAAI,MAAIL,MAAI,KAAGA,MAAI,MAAI,gBAAAW,EAAC,QAAA,EAAuB,GAAGX,GAAG,GAAGK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAK,gBAAe,SAASA,KAAG,IAAE,MAAG,EAAA,GAAnF,GAAGA,CAAC,IAAIL,CAAC,EAA4E,IAAG,IAAI,CAAC;AAAA,IACvM,gBAAAW,EAAC,QAAA,EAAK,GAAE,2BAA0B,WAAU,UAAA,CAAU;AAAA,EAAA,GACxD;AACF;"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AdminContent as n, AdminNavigation as o, AdminShell as e } from "./admin.js";
|
|
2
|
+
import { adminManifestProblem as m, adminPages as r } from "./model.js";
|
|
3
|
+
import { AdminDirectory as c, AdminFacts as a, AdminRecordButton as v } from "./directory.js";
|
|
4
|
+
import { IdentityAvatar as p } from "./identity-avatar.js";
|
|
5
|
+
import { ActivityGroup as x, ActivityMetric as l, ActivityRecord as s, ActivityStatus as u } from "./activity-directory.js";
|
|
6
|
+
import { ActivityActionButton as B, ActivityDialog as S, ActivityFacts as F, ActivitySection as T } from "./activity-dialog.js";
|
|
7
|
+
import { ActivityBars as D, ActivityTimeline as I } from "./activity-history.js";
|
|
8
|
+
import { AdminActionButton as P, AdminBadge as R, AdminFact as h, AdminField as C, AdminHeading as G, AdminInput as H, AdminSection as N, AdminSelect as j, AdminTabs as k, AdminTextarea as q } from "./editor.js";
|
|
9
|
+
export {
|
|
10
|
+
B as ActivityActionButton,
|
|
11
|
+
D as ActivityBars,
|
|
12
|
+
S as ActivityDialog,
|
|
13
|
+
F as ActivityFacts,
|
|
14
|
+
x as ActivityGroup,
|
|
15
|
+
l as ActivityMetric,
|
|
16
|
+
s as ActivityRecord,
|
|
17
|
+
T as ActivitySection,
|
|
18
|
+
u as ActivityStatus,
|
|
19
|
+
I as ActivityTimeline,
|
|
20
|
+
P as AdminActionButton,
|
|
21
|
+
R as AdminBadge,
|
|
22
|
+
n as AdminContent,
|
|
23
|
+
c as AdminDirectory,
|
|
24
|
+
h as AdminFact,
|
|
25
|
+
a as AdminFacts,
|
|
26
|
+
C as AdminField,
|
|
27
|
+
G as AdminHeading,
|
|
28
|
+
H as AdminInput,
|
|
29
|
+
o as AdminNavigation,
|
|
30
|
+
v as AdminRecordButton,
|
|
31
|
+
N as AdminSection,
|
|
32
|
+
j as AdminSelect,
|
|
33
|
+
e as AdminShell,
|
|
34
|
+
k as AdminTabs,
|
|
35
|
+
q as AdminTextarea,
|
|
36
|
+
p as IdentityAvatar,
|
|
37
|
+
m as adminManifestProblem,
|
|
38
|
+
r as adminPages
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const n = (t) => typeof t == "object" && t !== null && !Array.isArray(t), r = (t) => typeof t == "string" && t.trim().length > 0, d = { settings: "settings", health: "status", stats: "status", series: "diagnostics", diagnostics: "diagnostics" };
|
|
2
|
+
function c(t) {
|
|
3
|
+
if (!n(t)) return "Malformed admin manifest.";
|
|
4
|
+
if (t.contract_version !== 1) return "Unsupported admin contract version.";
|
|
5
|
+
if (!n(t.app) || !r(t.app.id) || !r(t.app.label) || !r(t.revision)) return "Malformed admin identity or declaration revision.";
|
|
6
|
+
for (const [e, i] of Object.entries(d)) {
|
|
7
|
+
const o = t[e];
|
|
8
|
+
if (!Array.isArray(o)) return `Malformed admin manifest: missing ${e} array.`;
|
|
9
|
+
const a = /* @__PURE__ */ new Set();
|
|
10
|
+
for (const s of o) {
|
|
11
|
+
if (!n(s) || !r(s.id) || !r(s.label) || a.has(s.id)) return `Malformed ${e} resource identity.`;
|
|
12
|
+
if (a.add(s.id), s.section !== i) return `Contradictory ${e} section: resources must declare ${i}.`;
|
|
13
|
+
if (e !== "settings" && (typeof s.stale_after_ms != "number" || !Number.isFinite(s.stale_after_ms) || s.stale_after_ms <= 0)) return `Unsupported ${e} observation age declaration.`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function f(t) {
|
|
18
|
+
return ["dashboard", ...t.settings.length ? ["settings"] : [], ...t.health.length || t.stats.length ? ["status"] : [], ...t.series.length || t.diagnostics.length ? ["diagnostics"] : []];
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
c as adminManifestProblem,
|
|
22
|
+
f as adminPages
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sources":["../src/model.ts"],"sourcesContent":["import type { AdminManifest, AdminPage } from './types'\n\nconst record = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)\nconst text = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0\nconst sections = { settings: 'settings', health: 'status', stats: 'status', series: 'diagnostics', diagnostics: 'diagnostics' } as const\n\n/** Presentation fence, not a wire validator. Never relocate a contradictory resource. */\nexport function adminManifestProblem(value: unknown): string | undefined {\n if (!record(value)) return 'Malformed admin manifest.'\n if (value.contract_version !== 1) return 'Unsupported admin contract version.'\n if (!record(value.app) || !text(value.app.id) || !text(value.app.label) || !text(value.revision)) return 'Malformed admin identity or declaration revision.'\n for (const [kind, section] of Object.entries(sections)) {\n const resources = value[kind]\n if (!Array.isArray(resources)) return `Malformed admin manifest: missing ${kind} array.`\n const ids = new Set<string>()\n for (const resource of resources) {\n if (!record(resource) || !text(resource.id) || !text(resource.label) || ids.has(resource.id)) return `Malformed ${kind} resource identity.`\n ids.add(resource.id)\n if (resource.section !== section) return `Contradictory ${kind} section: resources must declare ${section}.`\n if (kind !== 'settings' && (typeof resource.stale_after_ms !== 'number' || !Number.isFinite(resource.stale_after_ms) || resource.stale_after_ms <= 0)) return `Unsupported ${kind} observation age declaration.`\n }\n }\n}\nexport function adminPages(manifest: AdminManifest): readonly AdminPage[] {\n return ['dashboard', ...(manifest.settings.length ? ['settings' as const] : []), ...(manifest.health.length || manifest.stats.length ? ['status' as const] : []), ...(manifest.series.length || manifest.diagnostics.length ? ['diagnostics' as const] : [])]\n}\n"],"names":["record","v","text","sections","adminManifestProblem","value","kind","section","resources","ids","resource","adminPages","manifest"],"mappings":"AAEA,MAAMA,IAAS,CAACC,MAA6C,OAAOA,KAAM,YAAYA,MAAM,QAAQ,CAAC,MAAM,QAAQA,CAAC,GAC9GC,IAAO,CAACD,MAA4B,OAAOA,KAAM,YAAYA,EAAE,OAAO,SAAS,GAC/EE,IAAW,EAAE,UAAU,YAAY,QAAQ,UAAU,OAAO,UAAU,QAAQ,eAAe,aAAa,cAAA;AAGzG,SAASC,EAAqBC,GAAoC;AACvE,MAAI,CAACL,EAAOK,CAAK,EAAG,QAAO;AAC3B,MAAIA,EAAM,qBAAqB,EAAG,QAAO;AACzC,MAAI,CAACL,EAAOK,EAAM,GAAG,KAAK,CAACH,EAAKG,EAAM,IAAI,EAAE,KAAK,CAACH,EAAKG,EAAM,IAAI,KAAK,KAAK,CAACH,EAAKG,EAAM,QAAQ,EAAG,QAAO;AACzG,aAAW,CAACC,GAAMC,CAAO,KAAK,OAAO,QAAQJ,CAAQ,GAAG;AACtD,UAAMK,IAAYH,EAAMC,CAAI;AAC5B,QAAI,CAAC,MAAM,QAAQE,CAAS,EAAG,QAAO,qCAAqCF,CAAI;AAC/E,UAAMG,wBAAU,IAAA;AAChB,eAAWC,KAAYF,GAAW;AAChC,UAAI,CAACR,EAAOU,CAAQ,KAAK,CAACR,EAAKQ,EAAS,EAAE,KAAK,CAACR,EAAKQ,EAAS,KAAK,KAAKD,EAAI,IAAIC,EAAS,EAAE,EAAG,QAAO,aAAaJ,CAAI;AAEtH,UADAG,EAAI,IAAIC,EAAS,EAAE,GACfA,EAAS,YAAYH,UAAgB,iBAAiBD,CAAI,oCAAoCC,CAAO;AACzG,UAAID,MAAS,eAAe,OAAOI,EAAS,kBAAmB,YAAY,CAAC,OAAO,SAASA,EAAS,cAAc,KAAKA,EAAS,kBAAkB,GAAI,QAAO,eAAeJ,CAAI;AAAA,IACnL;AAAA,EACF;AACF;AACO,SAASK,EAAWC,GAA+C;AACxE,SAAO,CAAC,aAAa,GAAIA,EAAS,SAAS,SAAS,CAAC,UAAmB,IAAI,CAAA,GAAK,GAAIA,EAAS,OAAO,UAAUA,EAAS,MAAM,SAAS,CAAC,QAAiB,IAAI,IAAK,GAAIA,EAAS,OAAO,UAAUA,EAAS,YAAY,SAAS,CAAC,aAAsB,IAAI,CAAA,CAAG;AAC9P;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
/** Content-sized activity inspection. The host owns selection and evidence;
|
|
3
|
+
* the dialog primitive owns focus, Escape and the viewport's scrolling. */
|
|
4
|
+
export declare function ActivityDialog({ open, onClose, title, avatar, description, metadata, status, accessory, score, children }: {
|
|
5
|
+
open: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
title: string;
|
|
8
|
+
avatar: ReactNode;
|
|
9
|
+
description: ReactNode;
|
|
10
|
+
metadata?: ReactNode;
|
|
11
|
+
status: ReactNode;
|
|
12
|
+
accessory?: ReactNode;
|
|
13
|
+
score?: ReactNode;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
16
|
+
/** Dense value-first facts, with full values available as text/title. */
|
|
17
|
+
export declare function ActivityFacts({ label, items }: {
|
|
18
|
+
label?: string;
|
|
19
|
+
items: {
|
|
20
|
+
label: string;
|
|
21
|
+
value: ReactNode;
|
|
22
|
+
title?: string;
|
|
23
|
+
}[];
|
|
24
|
+
}): import("react").JSX.Element;
|
|
25
|
+
/** Compact observation/action section, without an additional card surface. */
|
|
26
|
+
export declare function ActivitySection({ title, children, spacing }: {
|
|
27
|
+
title: string;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
spacing?: 'default' | 'tight';
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
/** Small outlined action for activity inspectors; availability is host-owned. */
|
|
32
|
+
export declare function ActivityActionButton({ className, type, ...props }: ComponentProps<'button'>): import("react").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** Compact grouped activity list. Ranking and aggregation remain host-owned. */
|
|
3
|
+
export declare function ActivityGroup({ title, metadata, summary, children }: {
|
|
4
|
+
title: string;
|
|
5
|
+
metadata?: ReactNode;
|
|
6
|
+
summary?: ReactNode;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
/** Value-first metric, shared by activity rows and detail summaries. */
|
|
10
|
+
export declare function ActivityMetric({ label, value, title, highlight, size }: {
|
|
11
|
+
label: string;
|
|
12
|
+
value: ReactNode;
|
|
13
|
+
title?: string;
|
|
14
|
+
highlight?: boolean;
|
|
15
|
+
size?: 'default' | 'prominent';
|
|
16
|
+
}): import("react").JSX.Element;
|
|
17
|
+
/** Unboxed status for dense activity lists. A label always accompanies the dot. */
|
|
18
|
+
export declare function ActivityStatus({ label, detail, tone }: {
|
|
19
|
+
label: string;
|
|
20
|
+
detail?: string;
|
|
21
|
+
tone?: 'positive' | 'attention' | 'neutral' | 'muted';
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/** One inspectable identity with aligned ranks, metrics and optional history.
|
|
24
|
+
* Slots are presentation only; the host supplies evidence and handles selection. */
|
|
25
|
+
export declare function ActivityRecord({ label, onSelect, rank, avatar, name, metadata, description, status, metrics, history, accessory, score, muted, attention }: {
|
|
26
|
+
label: string;
|
|
27
|
+
onSelect: () => void;
|
|
28
|
+
rank: ReactNode;
|
|
29
|
+
avatar: ReactNode;
|
|
30
|
+
name: string;
|
|
31
|
+
metadata?: ReactNode;
|
|
32
|
+
description?: ReactNode;
|
|
33
|
+
status: ReactNode;
|
|
34
|
+
metrics?: ReactNode;
|
|
35
|
+
history?: ReactNode;
|
|
36
|
+
accessory?: ReactNode;
|
|
37
|
+
score: ReactNode;
|
|
38
|
+
muted?: boolean;
|
|
39
|
+
attention?: boolean;
|
|
40
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ActivityTone = 'positive' | 'attention' | 'neutral' | 'muted';
|
|
2
|
+
/** Normalized observed intervals. Empty areas remain unpainted, not idle. */
|
|
3
|
+
export declare function ActivityTimeline({ label, segments, size }: {
|
|
4
|
+
label: string;
|
|
5
|
+
segments: {
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
label: string;
|
|
9
|
+
tone: ActivityTone;
|
|
10
|
+
}[];
|
|
11
|
+
size?: 'default' | 'compact';
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
/** A frozen activity sparkline. null buckets are unobserved; zero is observed. */
|
|
14
|
+
export declare function ActivityBars({ label, values, tone }: {
|
|
15
|
+
label: string;
|
|
16
|
+
values: (number | null)[];
|
|
17
|
+
tone?: ActivityTone;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AdminContentProps } from './types';
|
|
2
|
+
/** Navigation is only a projection of declared sections; the host owns routing/history. */
|
|
3
|
+
export declare function AdminNavigation(props: AdminContentProps): import("react").JSX.Element;
|
|
4
|
+
/** Inner region for an existing host shell; no viewport wrapper, effects or local data store. */
|
|
5
|
+
export declare function AdminContent(props: AdminContentProps): import("react").JSX.Element;
|
|
6
|
+
/** Standalone viewport composition. Use AdminContent inside an existing AppShell instead. */
|
|
7
|
+
export declare function AdminShell(props: AdminContentProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** Controlled record directory. The app owns filtering, selection, drafts and commands. */
|
|
3
|
+
export declare function AdminDirectory({ label, records, detail, controls, layout }: {
|
|
4
|
+
label: string;
|
|
5
|
+
records: ReactNode;
|
|
6
|
+
detail: ReactNode;
|
|
7
|
+
controls?: ReactNode;
|
|
8
|
+
layout?: 'balanced' | 'wide' | 'compact';
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/** One selectable directory row with shared type, spacing and selected/keyboard feedback. */
|
|
11
|
+
export declare function AdminRecordButton({ title, description, avatar, badge, selected, onSelect, muted }: {
|
|
12
|
+
title: ReactNode;
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
avatar?: ReactNode;
|
|
15
|
+
badge?: ReactNode;
|
|
16
|
+
selected: boolean;
|
|
17
|
+
onSelect: () => void;
|
|
18
|
+
muted?: boolean; /** @deprecated Both legacy sizes now follow the dashboard typography profile. */
|
|
19
|
+
size?: 'default' | 'comfortable';
|
|
20
|
+
}): import("react").JSX.Element;
|
|
21
|
+
/** Reusable metadata presentation; missing values stay explicit. */
|
|
22
|
+
export declare function AdminFacts({ items }: {
|
|
23
|
+
items: {
|
|
24
|
+
label: string;
|
|
25
|
+
value: ReactNode;
|
|
26
|
+
}[];
|
|
27
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
import { Input, Textarea } from '@hollis-labs/design-components';
|
|
3
|
+
/** Configuration section shared by inspectors, editors and review plans. */
|
|
4
|
+
export declare function AdminHeading({ children }: {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
export declare function AdminSection({ title, children }: {
|
|
8
|
+
title: string;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
/** A semantic definition pair. Supply application-specific missing-value text. */
|
|
12
|
+
export declare function AdminFact({ label, children }: {
|
|
13
|
+
label: string;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
16
|
+
export declare function AdminBadge({ className, ...props }: ComponentProps<'span'>): import("react").JSX.Element;
|
|
17
|
+
/** Standard button behavior with the compact configuration idiom. */
|
|
18
|
+
export declare function AdminActionButton({ tone, className, type, ...props }: ComponentProps<'button'> & {
|
|
19
|
+
tone?: 'primary' | 'danger' | 'ghost';
|
|
20
|
+
}): import("react").JSX.Element;
|
|
21
|
+
/** Controlled tabs: the base primitive owns arrow-key navigation and disabled tabs. */
|
|
22
|
+
export declare function AdminTabs<K extends string>({ label, value, onChange, items, actions }: {
|
|
23
|
+
label: string;
|
|
24
|
+
value: K;
|
|
25
|
+
onChange: (value: K) => void;
|
|
26
|
+
items: readonly {
|
|
27
|
+
key: K;
|
|
28
|
+
label: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
title?: string;
|
|
31
|
+
}[];
|
|
32
|
+
actions?: ReactNode;
|
|
33
|
+
}): import("react").JSX.Element;
|
|
34
|
+
/** Validation remains host-owned; field presentation is shared. */
|
|
35
|
+
export declare function AdminField({ label, htmlFor, changed, issues, children }: {
|
|
36
|
+
label: string;
|
|
37
|
+
htmlFor?: string;
|
|
38
|
+
changed?: boolean;
|
|
39
|
+
issues?: readonly {
|
|
40
|
+
level: string;
|
|
41
|
+
message: string;
|
|
42
|
+
}[];
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
}): import("react").JSX.Element;
|
|
45
|
+
export declare function AdminInput({ className, ...props }: ComponentProps<typeof Input>): import("react").JSX.Element;
|
|
46
|
+
/** Native select preserves option/form semantics and uses dashboard control tokens. */
|
|
47
|
+
export declare function AdminSelect({ className, ...props }: ComponentProps<'select'>): import("react").JSX.Element;
|
|
48
|
+
export declare function AdminTextarea({ className, ...props }: ComponentProps<typeof Textarea>): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { AdminContent, AdminNavigation, AdminShell } from './admin';
|
|
2
|
+
export { adminManifestProblem, adminPages } from './model';
|
|
3
|
+
export type { AdminContentProps, AdminDeclaration, AdminObservationDeclaration, AdminSettingsDeclaration, AdminStatDeclaration, AdminSeriesDeclaration, AdminDiagnosticDeclaration, AdminManifest, AdminPage, AdminTarget, AdminDestination, AdminSelection, AdminDiscovery, AdminSettingsRead, AdminObservations } from './types';
|
|
4
|
+
export { AdminDirectory, AdminRecordButton, AdminFacts } from './directory';
|
|
5
|
+
export { IdentityAvatar } from './identity-avatar';
|
|
6
|
+
export { ActivityGroup, ActivityMetric, ActivityRecord, ActivityStatus } from './activity-directory';
|
|
7
|
+
export { ActivityDialog, ActivityFacts, ActivitySection, ActivityActionButton } from './activity-dialog';
|
|
8
|
+
export { ActivityTimeline, ActivityBars } from './activity-history';
|
|
9
|
+
export type { ActivityTone } from './activity-history';
|
|
10
|
+
export { AdminHeading, AdminSection, AdminFact, AdminBadge, AdminActionButton, AdminTabs, AdminField, AdminInput, AdminSelect, AdminTextarea } from './editor';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AdminManifest, AdminPage } from './types';
|
|
2
|
+
/** Presentation fence, not a wire validator. Never relocate a contradictory resource. */
|
|
3
|
+
export declare function adminManifestProblem(value: unknown): string | undefined;
|
|
4
|
+
export declare function adminPages(manifest: AdminManifest): readonly AdminPage[];
|