@hanzo/ui 8.0.23 → 8.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +59 -0
  2. package/dist/chunk-3NG33DV2.cjs +607 -0
  3. package/dist/chunk-3NG33DV2.cjs.map +1 -0
  4. package/dist/chunk-5CZOYONP.js +343 -0
  5. package/dist/chunk-5CZOYONP.js.map +1 -0
  6. package/dist/{chunk-P2P6ST6J.js → chunk-7ZNK6JSS.js} +9 -394
  7. package/dist/chunk-7ZNK6JSS.js.map +1 -0
  8. package/dist/chunk-GVCOAJLO.js +397 -0
  9. package/dist/chunk-GVCOAJLO.js.map +1 -0
  10. package/dist/chunk-GWNNLYX4.cjs +353 -0
  11. package/dist/chunk-GWNNLYX4.cjs.map +1 -0
  12. package/dist/{chunk-NBZDIMP3.cjs → chunk-ONVERVFG.cjs} +33 -438
  13. package/dist/chunk-ONVERVFG.cjs.map +1 -0
  14. package/dist/chunk-P2QU5MN5.js +555 -0
  15. package/dist/chunk-P2QU5MN5.js.map +1 -0
  16. package/dist/chunk-WHJR5S4L.cjs +418 -0
  17. package/dist/chunk-WHJR5S4L.cjs.map +1 -0
  18. package/dist/framework/CollectionBuilder.d.ts +12 -0
  19. package/dist/framework/CollectionsBrowser.d.ts +26 -19
  20. package/dist/framework/DocTypeRecords.d.ts +31 -11
  21. package/dist/framework/MediaGrid.d.ts +42 -0
  22. package/dist/framework/RecordCards.d.ts +35 -0
  23. package/dist/framework/builder-logic.d.ts +76 -0
  24. package/dist/framework/client.d.ts +31 -44
  25. package/dist/framework/core.cjs +213 -0
  26. package/dist/framework/core.cjs.map +1 -0
  27. package/dist/framework/core.d.ts +6 -0
  28. package/dist/framework/core.js +4 -0
  29. package/dist/framework/core.js.map +1 -0
  30. package/dist/framework/data.d.ts +2 -2
  31. package/dist/framework/fields.d.ts +47 -4
  32. package/dist/framework/index.cjs +1340 -0
  33. package/dist/framework/index.cjs.map +1 -0
  34. package/dist/framework/index.d.ts +9 -23
  35. package/dist/framework/index.js +1119 -0
  36. package/dist/framework/index.js.map +1 -0
  37. package/dist/framework/media.d.ts +53 -0
  38. package/dist/framework/parts.d.ts +74 -0
  39. package/dist/framework/responsive.d.ts +41 -0
  40. package/dist/framework/types.d.ts +13 -7
  41. package/dist/product/SelectMenu.d.ts +13 -1
  42. package/dist/product/index.cjs +2061 -336
  43. package/dist/product/index.cjs.map +1 -1
  44. package/dist/product/index.js +1909 -3
  45. package/dist/product/index.js.map +1 -1
  46. package/dist/product/social/index.cjs +17 -16
  47. package/dist/product/social/index.js +3 -2
  48. package/package.json +11 -5
  49. package/dist/chunk-2BM42AZR.cjs +0 -2301
  50. package/dist/chunk-2BM42AZR.cjs.map +0 -1
  51. package/dist/chunk-7P7R7FC5.js +0 -2231
  52. package/dist/chunk-7P7R7FC5.js.map +0 -1
  53. package/dist/chunk-NBZDIMP3.cjs.map +0 -1
  54. package/dist/chunk-P2P6ST6J.js.map +0 -1
  55. package/dist/framework/Loader.d.ts +0 -4
  56. package/dist/framework.cjs +0 -757
  57. package/dist/framework.cjs.map +0 -1
  58. package/dist/framework.d.ts +0 -1
  59. package/dist/framework.js +0 -727
  60. package/dist/framework.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/framework/types.ts","../src/framework/client.ts","../src/framework/fields.ts","../src/framework/builder-logic.ts","../src/framework/media.ts","../src/framework/data.ts"],"names":[],"mappings":"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","file":"chunk-3NG33DV2.cjs","sourcesContent":["/**\n * The Hanzo Framework wire contract — the DocType / DocField / document shapes the\n * cloud `clients/framework` engine serves at `/v1/framework/*` (Frappe's DocType\n * metadata core, rebuilt native in Go; also published standalone as\n * github.com/hanzoai/doctype). These mirror the Go JSON tags exactly.\n *\n * This is the ONE metadata vocabulary the generic renderer builds from, so\n * CMS / ERP / CRM / Helpdesk — all \"just DocTypes\" on one engine — render through\n * the SAME components. Types only; no runtime, no imports, so a host's data layer\n * or a node test can depend on this file alone.\n */\n\n/** The engine's closed fieldtype set (mirrors doctype.Fieldtype). */\nexport type Fieldtype =\n | 'Data'\n | 'Int'\n | 'Float'\n | 'Currency'\n | 'Check'\n | 'Date'\n | 'Datetime'\n | 'Text'\n | 'SmallText'\n | 'LongText'\n | 'RichText'\n | 'Select'\n | 'Link'\n | 'Table'\n | 'Attach'\n | 'JSON'\n | 'Password'\n\n/** One field of a DocType (Frappe's DocField). */\nexport interface DocField {\n fieldname: string\n fieldtype: Fieldtype\n label?: string\n reqd?: boolean\n /** Select → newline-separated choices; Link → target DocType; Table → child DocType. */\n options?: string\n default?: string\n unique?: boolean\n readOnly?: boolean\n hidden?: boolean\n inListView?: boolean\n fetchFrom?: string\n}\n\n/** A role's rights on a DocType (Frappe's DocPerm). */\nexport interface DocPerm {\n role: string\n read?: boolean\n write?: boolean\n create?: boolean\n delete?: boolean\n submit?: boolean\n cancel?: boolean\n}\n\n/** A DocType definition — per-org metadata. */\nexport interface DocType {\n name: string\n module?: string\n isSingle?: boolean\n isSubmittable?: boolean\n autoname?: string\n titleField?: string\n fields: DocField[]\n permissions?: DocPerm[]\n createdAt?: number\n updatedAt?: number\n}\n\n/** The managed document envelope keys the engine always returns. */\nexport interface DocEnvelope {\n name: string\n doctype: string\n /** 0 = draft, 1 = submitted, 2 = cancelled. */\n docstatus: number\n createdAt: number\n updatedAt: number\n}\n\n/** A document: the field data overlaid with the managed envelope keys. */\nexport type FrameworkDoc = Record<string, unknown> & DocEnvelope\n\n/** The three docstatus values, named — so no view compares bare integers. */\nexport const DRAFT = 0\nexport const SUBMITTED = 1\nexport const CANCELLED = 2\n\n/** A registered app lane and (optionally, per-org) which fixtures are installed. */\nexport interface ModuleInfo {\n module: string\n doctypes: string[]\n installed?: string[]\n}\n\n/** The result of installing a module into the caller's org. */\nexport interface InstallResult {\n module: string\n created: string[]\n existing: string[]\n}\n\n/** List query for the generic document surface. */\nexport interface ListQuery {\n filters?: Record<string, string | number | boolean>\n fields?: string[]\n orderBy?: string\n limit?: number\n}\n\n/** The redacted-Password marker the engine returns for a set secret. */\nexport const REDACTED_MARKER = '__set__'\n","/**\n * The generic client for the Hanzo Framework DocType engine (`/v1/framework/*`).\n * It is metadata-driven and doctype-agnostic: the SAME `records` CRUD serves a CMS\n * Page, an ERP Invoice, or a Helpdesk Ticket — an app lane is just a `module`\n * filter over `doctypes`.\n *\n * THE HOST OWNS TRANSPORT. This module never picks an origin, a credential, or a\n * proxy: it takes a `FrameworkTransport` and builds paths RELATIVE to the framework\n * root (`doctypes`, `Article/hello`, `modules/cms/install`). The console maps those\n * onto its own user-bearer `/v1/framework/...` proxy; a native app or a test maps\n * them somewhere else. One client, any host.\n *\n * Names (DocType + document) go verbatim into the path, so they are\n * `encodeURIComponent`-escaped here and kept slug-style on create (`slugify`).\n * Payloads are read defensively from `{ data }` (or a bare array), so a shape drift\n * degrades a list rather than throwing.\n */\nimport type {\n DocType,\n FrameworkDoc,\n InstallResult,\n ListQuery,\n ModuleInfo,\n} from './types'\n\n/**\n * The ONE seam a host injects. Paths are relative to the framework root and never\n * start with a slash; the host prefixes its own base (and adds credentials).\n */\nexport interface FrameworkTransport {\n get: (path: string) => Promise<unknown>\n post: (path: string, body?: unknown) => Promise<unknown>\n put: (path: string, body?: unknown) => Promise<unknown>\n del: (path: string) => Promise<void>\n}\n\n/** The name 8.0.24 shipped for the same seam. One concept, one shape, two spellings. */\nexport type Transport = FrameworkTransport\n\nconst enc = encodeURIComponent\n\nconst asRecord = (v: unknown): Record<string, unknown> =>\n v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : {}\n\n/** Pull the first array under a common envelope key (the engine uses `data`). */\nexport function rows(payload: unknown): Record<string, unknown>[] {\n if (Array.isArray(payload)) {\n return payload.filter((x) => x && typeof x === 'object') as Record<string, unknown>[]\n }\n const o = asRecord(payload)\n for (const k of ['data', 'items', 'rows']) {\n if (Array.isArray(o[k])) {\n return (o[k] as unknown[]).filter((x) => x && typeof x === 'object') as Record<string, unknown>[]\n }\n }\n return []\n}\n\n/** A framework document is already a flat map + envelope; keep it as-is (typed). */\nconst asDoc = (v: unknown): FrameworkDoc => asRecord(v) as FrameworkDoc\n\nconst asDocType = (v: unknown): DocType => {\n const r = asRecord(v)\n return {\n ...(r as object),\n name: String(r.name ?? ''),\n fields: Array.isArray(r.fields) ? (r.fields as DocType['fields']) : [],\n } as DocType\n}\n\n/** Build the generic document list querystring from a typed ListQuery. Pure. */\nexport function listQuery(q?: ListQuery): string {\n if (!q) return ''\n const p = new URLSearchParams()\n if (q.filters && Object.keys(q.filters).length) p.set('filters', JSON.stringify(q.filters))\n if (q.fields && q.fields.length) p.set('fields', q.fields.join(','))\n if (q.orderBy) p.set('order_by', q.orderBy)\n if (q.limit) p.set('limit', String(q.limit))\n const s = p.toString()\n return s ? `?${s}` : ''\n}\n\n/** The engine surface, as consumed by every DocType view. */\nexport interface FrameworkClient {\n /** The DocType registry (schemas) — the collection definitions of every app lane. */\n doctypes: {\n list: () => Promise<DocType[]>\n get: (name: string) => Promise<DocType>\n create: (dt: DocType) => Promise<DocType>\n update: (name: string, dt: DocType) => Promise<DocType>\n remove: (name: string) => Promise<void>\n }\n /** Generic, metadata-driven document CRUD — the SAME calls for ANY doctype. */\n records: {\n list: (doctype: string, q?: ListQuery) => Promise<FrameworkDoc[]>\n get: (doctype: string, name: string) => Promise<FrameworkDoc>\n create: (doctype: string, data: Record<string, unknown>) => Promise<FrameworkDoc>\n update: (doctype: string, name: string, data: Record<string, unknown>) => Promise<FrameworkDoc>\n remove: (doctype: string, name: string) => Promise<void>\n submit: (doctype: string, name: string) => Promise<FrameworkDoc>\n cancel: (doctype: string, name: string) => Promise<FrameworkDoc>\n }\n /** App-lane fixtures: list the registered lanes, inspect one, install into the org. */\n modules: {\n list: () => Promise<ModuleInfo[]>\n get: (module: string) => Promise<ModuleInfo>\n install: (module: string) => Promise<InstallResult>\n }\n /** Per-org role assignments (grant editors; the owner is seeded System Manager). */\n roles: {\n list: () => Promise<{ user: string; role: string }[]>\n assign: (user: string, role: string) => Promise<void>\n revoke: (user: string, role: string) => Promise<void>\n }\n /** Engine health/reach probe — `GET /summary`. */\n summary: () => Promise<Record<string, unknown>>\n}\n\n/** Bind the framework surface to a host's transport. */\nexport function createFrameworkClient(t: FrameworkTransport): FrameworkClient {\n return {\n doctypes: {\n list: () => t.get('doctypes').then((r) => rows(r).map(asDocType)),\n get: (name) => t.get(`doctypes/${enc(name)}`).then(asDocType),\n create: (dt) => t.post('doctypes', dt).then(asDocType),\n update: (name, dt) => t.put(`doctypes/${enc(name)}`, dt).then(asDocType),\n remove: (name) => t.del(`doctypes/${enc(name)}`),\n },\n\n records: {\n list: (doctype, q) => t.get(`${enc(doctype)}${listQuery(q)}`).then((r) => rows(r).map(asDoc)),\n get: (doctype, name) => t.get(`${enc(doctype)}/${enc(name)}`).then(asDoc),\n create: (doctype, data) => t.post(enc(doctype), data).then(asDoc),\n update: (doctype, name, data) => t.put(`${enc(doctype)}/${enc(name)}`, data).then(asDoc),\n remove: (doctype, name) => t.del(`${enc(doctype)}/${enc(name)}`),\n submit: (doctype, name) => t.post(`${enc(doctype)}/${enc(name)}/submit`).then(asDoc),\n cancel: (doctype, name) => t.post(`${enc(doctype)}/${enc(name)}/cancel`).then(asDoc),\n },\n\n modules: {\n list: () =>\n t.get('modules').then((r) =>\n rows(r).map((m) => ({\n module: String(m.module ?? ''),\n doctypes: Array.isArray(m.doctypes) ? (m.doctypes as string[]) : [],\n })),\n ),\n get: (module) =>\n t.get(`modules/${enc(module)}`).then((v) => {\n const r = asRecord(v)\n return {\n module: String(r.module ?? module),\n doctypes: Array.isArray(r.doctypes) ? (r.doctypes as string[]) : [],\n installed: Array.isArray(r.installed) ? (r.installed as string[]) : [],\n }\n }),\n install: (module) =>\n t.post(`modules/${enc(module)}/install`).then((v) => {\n const r = asRecord(v)\n return {\n module: String(r.module ?? module),\n created: Array.isArray(r.created) ? (r.created as string[]) : [],\n existing: Array.isArray(r.existing) ? (r.existing as string[]) : [],\n }\n }),\n },\n\n roles: {\n list: () =>\n t.get('roles').then((r) =>\n rows(r).map((x) => ({ user: String(x.user ?? ''), role: String(x.role ?? '') })),\n ),\n assign: (user, role) => t.post('roles', { user, role }).then(() => undefined),\n revoke: (user, role) => t.del(`roles/${enc(user)}/${enc(role)}`),\n },\n\n summary: () => t.get('summary').then(asRecord),\n }\n}\n","/**\n * Pure mapping between the Hanzo Framework DocType metadata and @hanzo/data's\n * render model — the brain of the generic DocType renderer. It is the ONE place\n * that translates the engine's Frappe field vocabulary into @hanzo/data's, so\n * EVERY app lane (CMS / ERP / CRM / Helpdesk) renders list, card, form and detail\n * identically with zero per-doctype code. A new DocType — or a whole new lane —\n * \"just works\".\n *\n * No I/O, no React — data in, data out, trivially testable (the @hanzo/data\n * imports are `import type`, erased at build, so the unit test runs in plain Node).\n */\nimport type { FieldDefinition, FieldType, SelectOption } from '@hanzo/data'\nimport type { DocField, DocType, FrameworkDoc } from './types'\nimport { DRAFT, REDACTED_MARKER } from './types'\n\n/**\n * Frappe fieldtype → @hanzo/data field type. 1:1 cases; the value shape each\n * needs is handled in `toRecord`/`savePayload` (currency object, boolean, etc).\n * Attach is a single asset URL → `url` (a clickable link + text input); a Table /\n * JSON renders as raw JSON (honest — no silent wrong guess). Password → `text`\n * (write-only; the value is never surfaced, only set).\n */\nconst TYPE_MAP: Record<DocField['fieldtype'], FieldType> = {\n Data: 'text',\n SmallText: 'text',\n Text: 'longText',\n LongText: 'longText',\n RichText: 'richText',\n Int: 'number',\n Float: 'number',\n Currency: 'currency',\n Check: 'boolean',\n Date: 'date',\n Datetime: 'dateTime',\n Select: 'select',\n Link: 'relation',\n Table: 'json',\n Attach: 'url',\n JSON: 'json',\n Password: 'text',\n}\n\nconst ACRONYMS = new Set(['id', 'url', 'seo', 'api', 'ip'])\n\n/** `first_name` / `firstName` → \"First Name\"; known acronyms upper-cased. */\nexport function humanize(name: string): string {\n return name\n .replace(/[_-]+/g, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => (ACRONYMS.has(w.toLowerCase()) ? w.toUpperCase() : w.charAt(0).toUpperCase() + w.slice(1)))\n .join(' ')\n}\n\n/** Select field's newline-separated choices → @hanzo/data options (blank dropped). */\nfunction selectOptions(options: string | undefined): SelectOption[] {\n return (options ?? '')\n .split('\\n')\n .map((s) => s.replace(/\\r$/, '').trim())\n .filter(Boolean)\n .map((v) => ({ value: v, label: v }))\n}\n\n/** Per-field @hanzo/data metadata (select options, currency code, relation target). */\nfunction metadataFor(f: DocField): FieldDefinition['metadata'] | undefined {\n switch (f.fieldtype) {\n case 'Select':\n return { options: selectOptions(f.options) }\n case 'Currency':\n return { currencyCode: 'USD' }\n case 'Int':\n return { decimals: 0 }\n case 'Link':\n return { objectName: f.options }\n default:\n return undefined\n }\n}\n\n/** The autoname source field for a `field:xxx` rule (`\"\"` otherwise). */\nexport function autonameSource(dt: DocType): string {\n const a = (dt.autoname ?? '').trim()\n return a.startsWith('field:') ? a.slice('field:'.length).trim() : ''\n}\n\nexport interface FieldMapOpts {\n /** Editing an existing record: the autoname-source field is fixed (the URL key). */\n editing?: boolean\n}\n\n/**\n * Map a DocType's fields to the ordered `FieldDefinition[]` every @hanzo/data view\n * renders from. Hidden fields are dropped; the engine's readOnly is honored; and\n * when editing an existing record the autoname source (e.g. `slug`) is made\n * read-only because it IS the document's immutable URL key.\n */\nexport function docTypeToFields(dt: DocType, opts: FieldMapOpts = {}): FieldDefinition[] {\n const src = autonameSource(dt)\n return (dt.fields ?? [])\n .filter((f) => !f.hidden)\n .map((f) => {\n const readOnly = f.readOnly || (opts.editing && f.fieldname === src) || undefined\n const metadata = metadataFor(f)\n return {\n name: f.fieldname,\n label: f.label || humanize(f.fieldname),\n type: TYPE_MAP[f.fieldtype] ?? 'text',\n ...(metadata ? { metadata } : {}),\n ...(readOnly ? { readOnly: true as const } : {}),\n }\n })\n}\n\n/** The status field a publishable content type uses (a Select including \"Published\"). */\nexport function statusField(dt: DocType): string {\n const f = (dt.fields ?? []).find(\n (x) => x.fieldtype === 'Select' && x.fieldname === 'status' && (x.options ?? '').includes('Published'),\n )\n return f ? f.fieldname : ''\n}\n\n/**\n * Field names hidden from the table grid: everything NOT flagged `inListView`\n * (when the DocType flags any). This is the engine's own column projection —\n * an ERP Sales Order declares 4 list columns out of 12 fields, so honoring it is\n * what keeps a wide DocType from becoming a horizontally-scrolling wall.\n */\nexport function listHiddenFields(dt: DocType): string[] {\n const anyListed = (dt.fields ?? []).some((f) => f.inListView)\n if (!anyListed) return []\n return (dt.fields ?? []).filter((f) => !f.inListView && !f.hidden).map((f) => f.fieldname)\n}\n\n/**\n * The fields shown on a MOBILE card, in order: the DocType's declared list columns\n * (`inListView`), else the first few visible fields. The title is rendered by the\n * card itself, so it is excluded here. Capped, because a card is a summary — the\n * full record is one tap away.\n */\nexport function cardFields(dt: DocType, fields: FieldDefinition[], max = 4): FieldDefinition[] {\n const title = dt.titleField ?? ''\n const listed = new Set(listedFieldNames(dt))\n const pick = listed.size ? fields.filter((f) => listed.has(f.name)) : fields\n return pick.filter((f) => f.name !== title).slice(0, max)\n}\n\n/** The `inListView` field names (empty when the DocType flags none). */\nexport function listedFieldNames(dt: DocType): string[] {\n return (dt.fields ?? []).filter((f) => f.inListView && !f.hidden).map((f) => f.fieldname)\n}\n\n/** True when a DocType is a media/asset library (a required Attach) → grid view. */\nexport function isMediaDoctype(dt: DocType): boolean {\n return (dt.fields ?? []).some((f) => f.fieldtype === 'Attach' && f.reqd)\n}\n\n/** The primary Attach field name (the asset URL) of a media doctype. */\nexport function mediaFileField(dt: DocType): string {\n const f =\n (dt.fields ?? []).find((x) => x.fieldtype === 'Attach' && x.reqd) ??\n (dt.fields ?? []).find((x) => x.fieldtype === 'Attach')\n return f ? f.fieldname : ''\n}\n\n/** The uploaded-asset facts a media DocType may want stored alongside the file. */\nexport interface MediaFacts {\n /** The `file`-field value (an object reference or URL). */\n fileRef: string\n filename: string\n mime: string\n size: number\n width: number\n height: number\n}\n\n/**\n * The create body for a media document — METADATA-DRIVEN, not a hardcoded CMS\n * schema. The file lands on the DocType's own Attach field, the filename on its\n * declared `titleField` (else `title` if it has one), and each optional fact\n * (`mime`/`size`/`width`/`height`) is written ONLY when the DocType actually\n * declares that field. A media collection that names its label `caption` gets a\n * captioned row instead of an untitled one, and a lane whose media DocType has no\n * dimensions never ships dead keys.\n */\nexport function mediaDocPayload(dt: DocType, facts: MediaFacts): Record<string, unknown> {\n const declared = new Set((dt.fields ?? []).map((f) => f.fieldname))\n const out: Record<string, unknown> = {}\n\n const fileField = mediaFileField(dt)\n if (fileField) out[fileField] = facts.fileRef\n\n const titleF = dt.titleField && declared.has(dt.titleField) ? dt.titleField : declared.has('title') ? 'title' : ''\n if (titleF && titleF !== fileField) out[titleF] = facts.filename\n\n const optional: [string, unknown][] = [\n ['mime', facts.mime],\n ['size', facts.size],\n ['width', facts.width],\n ['height', facts.height],\n ]\n for (const [k, v] of optional) if (declared.has(k) && k !== fileField && k !== titleF) out[k] = v\n\n return out\n}\n\n/** DocTypes belonging to an app lane (module) — a CMS \"collection\" is one of these. */\nexport function moduleDoctypes(dts: DocType[], module: string): DocType[] {\n return dts.filter((dt) => (dt.module ?? '') === module)\n}\n\n/** The conventional field a collection uses to scope documents to a project. */\nexport const PROJECT_FIELD = 'project'\n\n/** True when a DocType declares the `project` scope field (→ project filtering works). */\nexport function hasProjectField(dt: DocType): boolean {\n return (dt.fields ?? []).some((f) => f.fieldname === PROJECT_FIELD)\n}\n\n/**\n * The engine refuses to edit or delete a document that is no longer a draft\n * (`ops.go`: \"document is not a draft (docstatus %d); cannot edit\" and \"submitted\n * document must be cancelled before deletion\"). So the views ASK before offering\n * the affordance — a submitted invoice shows no Edit button rather than a full\n * form that errors on Save.\n */\nexport function isDraft(record: Record<string, unknown> | null | undefined): boolean {\n return Number(record?.docstatus ?? DRAFT) === DRAFT\n}\n\n/** A record's human title — the DocType's titleField, else its name. */\nexport function titleOf(doc: Record<string, unknown>, dt: DocType): string {\n if (dt.titleField && typeof doc[dt.titleField] === 'string' && doc[dt.titleField]) {\n return String(doc[dt.titleField])\n }\n return typeof doc.name === 'string' && doc.name ? doc.name : '(untitled)'\n}\n\n/**\n * URL-safe slug from arbitrary text: lower-case, any run of non-alphanumerics\n * collapsed to a single dash, ends trimmed. Guarantees a no-space, `%`-free\n * document name (the engine and a host's proxy path both require it).\n */\nexport function slugify(s: unknown): string {\n return String(s ?? '')\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '') // strip diacritics (accents → ASCII)\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n/** Valid Pascal/slug DocType name (letters/digits/dash/underscore, alnum-led, no space). */\nexport function isValidDoctypeName(name: string): boolean {\n return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(name.trim())\n}\n\nconst secToMs = (v: unknown): number | undefined => {\n const n = Number(v)\n return Number.isFinite(n) && n > 0 ? n * 1000 : undefined\n}\nconst numOrNull = (v: unknown): number | null => {\n const n = Number(v)\n return Number.isFinite(n) ? n : null\n}\n\n/** One field value, framework wire → @hanzo/data display shape. */\nfunction coerceForDisplay(f: DocField, v: unknown): unknown {\n switch (f.fieldtype) {\n case 'Currency':\n return { amount: numOrNull(v), currencyCode: 'USD' }\n case 'Check':\n return v === 1 || v === true || v === '1'\n case 'Datetime':\n return typeof v === 'string' ? v.replace(' ', 'T') : v\n case 'Password':\n return v === REDACTED_MARKER ? '' : v // never surface the marker\n default:\n return v\n }\n}\n\n/**\n * A framework document → a flat @hanzo/data record: the field values coerced to\n * their display shapes, plus `id` (the record key every view uses) and the managed\n * envelope. The ONE read mapping every DocType view shares.\n */\nexport function toRecord(doc: FrameworkDoc, dt: DocType): Record<string, unknown> {\n const rec: Record<string, unknown> = {\n id: doc.name,\n name: doc.name,\n doctype: doc.doctype,\n docstatus: doc.docstatus,\n createdAt: secToMs(doc.createdAt),\n updatedAt: secToMs(doc.updatedAt),\n }\n for (const f of dt.fields ?? []) {\n if (!(f.fieldname in doc)) continue\n rec[f.fieldname] = coerceForDisplay(f, doc[f.fieldname])\n }\n return rec\n}\n\n/** One draft value, @hanzo/data edit shape → framework wire. */\nfunction coerceForWrite(f: DocField, v: unknown): unknown {\n switch (f.fieldtype) {\n case 'Currency':\n return v && typeof v === 'object' && 'amount' in v ? Number((v as { amount: unknown }).amount) : Number(v)\n case 'Check':\n return Boolean(v)\n case 'Int':\n case 'Float':\n return Number(v)\n case 'Datetime':\n if (v instanceof Date) return v.toISOString()\n if (typeof v === 'number' && Number.isFinite(v)) return new Date(v).toISOString()\n return v\n case 'Link':\n // The picker stores a plain id (string); an unedited enriched value is\n // {id,label}; a cleared value is null. The engine wants the id string ('' = clear).\n if (v == null || v === '') return ''\n if (typeof v === 'object') {\n return String((v as { id?: unknown; value?: unknown }).id ?? (v as { value?: unknown }).value ?? '')\n }\n return v\n default:\n return v\n }\n}\n\n/**\n * Enrich a record's Link values with the target's human label ({id,label}), so a\n * relation renders as its title (not a raw id) in BOTH the list cell and the\n * detail — @hanzo/data's relation display reads `.label`, its input reads `.id`.\n * `optionsByField` is the loaded picker options per Link field (value=id, label=title).\n */\nexport function enrichLinks(\n record: Record<string, unknown>,\n dt: DocType,\n optionsByField: Record<string, SelectOption[]>,\n): Record<string, unknown> {\n const out = { ...record }\n for (const f of dt.fields ?? []) {\n if (f.fieldtype !== 'Link') continue\n const raw = out[f.fieldname]\n if (typeof raw === 'string' && raw) {\n const opt = (optionsByField[f.fieldname] ?? []).find((o) => o.value === raw)\n out[f.fieldname] = { id: raw, label: opt?.label ?? raw }\n }\n }\n return out\n}\n\n/** The Link fields of a DocType (their options must be loaded for the picker). */\nexport function linkFields(dt: DocType): DocField[] {\n return (dt.fields ?? []).filter((f) => f.fieldtype === 'Link')\n}\n\n/** A blank create-form draft seeded with each field's declared default (Check → bool). */\nexport function newDraft(dt: DocType): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const f of dt.fields ?? []) {\n if (f.default === undefined || f.default === '') continue\n out[f.fieldname] = f.fieldtype === 'Check' ? f.default === '1' || f.default === 'true' : f.default\n }\n return out\n}\n\n/**\n * A draft record → the framework write body: editable field values only (the\n * engine owns `name`/`docstatus`/timestamps), each coerced to its wire shape, and\n * the autoname source (e.g. `slug`) slugified so the document name is always URL-\n * safe. Fields left `undefined` are dropped — a partial edit never nulls a value.\n */\nexport function savePayload(draft: Record<string, unknown>, dt: DocType): Record<string, unknown> {\n const src = autonameSource(dt)\n const out: Record<string, unknown> = {}\n for (const f of dt.fields ?? []) {\n if (f.readOnly) continue // engine-owned; never written back\n let v = draft[f.fieldname]\n if (v === undefined) continue\n v = coerceForWrite(f, v)\n if (f.fieldname === src && typeof v === 'string') v = slugify(v)\n out[f.fieldname] = v\n }\n return out\n}\n","/**\n * Pure logic for the content-type builder — the model + validation + DocType\n * projection for defining a collection's fields on-page. No React, no I/O, so it\n * is unit-tested in plain Node. The builder UI is a thin shell over these.\n *\n * A \"collection\" is a framework DocType tagged with the lane module; a \"field\" is\n * a DocField. The builder offers exactly the engine's fieldtypes (mapped to\n * friendly labels), lets the author add/remove/reorder/require fields, and\n * projects the whole thing to a valid `DocType` create body. Names are slugified\n * to field-name rules so a save never 400s on a bad identifier.\n */\nimport type { DocType, DocField, Fieldtype } from './types'\nimport { slugify, isValidDoctypeName } from './fields'\n\n/**\n * The builder's field-type vocabulary — every framework fieldtype, with a friendly\n * label + hint. This is the ONE list the \"add field\" type picker renders, so the\n * builder always offers exactly what the engine accepts (no drift). Order is the\n * author-facing order (common types first).\n */\nexport const BUILDER_FIELD_TYPES: { type: Fieldtype; label: string; hint: string }[] = [\n { type: 'Data', label: 'Text', hint: 'Single line of text' },\n { type: 'RichText', label: 'Rich text', hint: 'Formatted body (WYSIWYG)' },\n { type: 'LongText', label: 'Long text', hint: 'Multi-line plain text' },\n { type: 'Int', label: 'Number', hint: 'Whole number' },\n { type: 'Float', label: 'Decimal', hint: 'Decimal number' },\n { type: 'Currency', label: 'Currency', hint: 'Money amount' },\n { type: 'Check', label: 'Checkbox', hint: 'True / false' },\n { type: 'Date', label: 'Date', hint: 'Calendar date' },\n { type: 'Datetime', label: 'Date & time', hint: 'Date with time' },\n { type: 'Select', label: 'Select', hint: 'One of a list of options' },\n { type: 'Link', label: 'Relation', hint: 'Reference another collection' },\n { type: 'Attach', label: 'Attachment', hint: 'A file / image URL' },\n { type: 'Table', label: 'Table', hint: 'Repeatable child rows (JSON)' },\n { type: 'JSON', label: 'JSON', hint: 'Arbitrary JSON' },\n]\n\nconst LABELS: Record<Fieldtype, string> = Object.fromEntries(\n BUILDER_FIELD_TYPES.map((t) => [t.type, t.label]),\n) as Record<Fieldtype, string>\n\n/** The friendly label for a fieldtype (falls back to the raw type). */\nexport function fieldTypeLabel(t: Fieldtype): string {\n return LABELS[t] ?? t\n}\n\n/** True when a fieldtype needs `options` (Select choices, Link/Table target). */\nexport function fieldNeedsOptions(t: Fieldtype): boolean {\n return t === 'Select' || t === 'Link' || t === 'Table'\n}\n\n/** One editable row in the builder — a superset of DocField the UI mutates. */\nexport interface BuilderField {\n /** Stable client key for React (not persisted). */\n key: string\n /** The field's label (author-facing); the fieldname is derived from it. */\n label: string\n type: Fieldtype\n required: boolean\n inListView: boolean\n /** Select → newline-joined choices; Link/Table → target collection name. */\n options: string\n}\n\nlet seq = 0\n/** A fresh, unique client key. */\nexport function newKey(): string {\n seq += 1\n return `f${seq}_${Math.random().toString(36).slice(2, 8)}`\n}\n\n/** A blank field row of a given type. */\nexport function blankField(type: Fieldtype = 'Data'): BuilderField {\n return { key: newKey(), label: '', type, required: false, inListView: false, options: '' }\n}\n\n/**\n * The default starter fields for a NEW content collection: a required Title, a URL\n * Slug (the autoname key), a rich Body, and a Draft/Published Status. The author\n * edits from here. Mirrors the cloud CMS seed so a hand-built collection matches a\n * seeded one.\n */\nexport function starterFields(): BuilderField[] {\n return [\n { key: newKey(), label: 'Title', type: 'Data', required: true, inListView: true, options: '' },\n { key: newKey(), label: 'Slug', type: 'Data', required: true, inListView: true, options: '' },\n { key: newKey(), label: 'Body', type: 'RichText', required: false, inListView: false, options: '' },\n { key: newKey(), label: 'Status', type: 'Select', required: false, inListView: true, options: 'Draft\\nPublished' },\n // Optional project scope — lets a host's org→project switcher filter this collection.\n { key: newKey(), label: 'Project', type: 'Data', required: false, inListView: false, options: '' },\n ]\n}\n\n/** An existing DocType → editable builder rows (drops engine-managed fields). */\nexport function fieldsFromDocType(dt: DocType): BuilderField[] {\n return (dt.fields ?? []).map((f) => ({\n key: newKey(),\n label: f.label || f.fieldname,\n type: f.fieldtype,\n required: Boolean(f.reqd),\n inListView: Boolean(f.inListView),\n options: f.options ?? '',\n }))\n}\n\n/** The fieldname derived from a label (slug with underscores; identifier-safe). */\nexport function fieldNameFromLabel(label: string): string {\n const slug = slugify(label).replace(/-/g, '_')\n // A leading digit isn't a valid identifier lead; prefix it.\n return /^[0-9]/.test(slug) ? `f_${slug}` : slug\n}\n\nexport interface BuilderValidation {\n ok: boolean\n /** Per-row error keyed by BuilderField.key. */\n fieldErrors: Record<string, string>\n /** A form-level error (name / no-fields). */\n formError: string | null\n}\n\n/**\n * Validate the whole builder: the collection name, at least one field, unique\n * non-empty field labels/names, and options present where required. Pure.\n */\nexport function validateBuilder(name: string, fields: BuilderField[]): BuilderValidation {\n const fieldErrors: Record<string, string> = {}\n let formError: string | null = null\n\n if (!isValidDoctypeName(name.trim())) {\n formError = 'Enter a collection name with letters, digits, dashes or underscores (no spaces).'\n } else if (fields.length === 0) {\n formError = 'Add at least one field.'\n }\n\n const seen = new Set<string>()\n for (const f of fields) {\n const label = f.label.trim()\n if (!label) {\n fieldErrors[f.key] = 'Name this field.'\n continue\n }\n const fname = fieldNameFromLabel(label)\n if (!fname) {\n fieldErrors[f.key] = 'Use letters or digits in the field name.'\n continue\n }\n if (seen.has(fname)) {\n fieldErrors[f.key] = `Duplicate field \"${fname}\".`\n continue\n }\n seen.add(fname)\n if ((f.type === 'Link' || f.type === 'Table') && !f.options.trim()) {\n fieldErrors[f.key] = f.type === 'Link' ? 'Choose the collection to relate to.' : 'Name the child collection.'\n } else if (f.type === 'Select' && !f.options.trim()) {\n fieldErrors[f.key] = 'Add at least one option.'\n }\n }\n\n return { ok: !formError && Object.keys(fieldErrors).length === 0, fieldErrors, formError }\n}\n\n/** A builder row → a framework DocField (drops UI-only bits, coerces options). */\nexport function toDocField(f: BuilderField): DocField {\n const fieldname = fieldNameFromLabel(f.label)\n const field: DocField = {\n fieldname,\n fieldtype: f.type,\n label: f.label.trim(),\n }\n if (f.required) field.reqd = true\n if (f.inListView) field.inListView = true\n if (fieldNeedsOptions(f.type) && f.options.trim()) field.options = f.options.trim()\n return field\n}\n\n/** Move a row within the ordered field list (a no-op at either end). Pure. */\nexport function moveField(fields: BuilderField[], key: string, dir: -1 | 1): BuilderField[] {\n const i = fields.findIndex((f) => f.key === key)\n const j = i + dir\n if (i < 0 || j < 0 || j >= fields.length) return fields\n const next = [...fields]\n ;[next[i], next[j]] = [next[j], next[i]]\n return next\n}\n\n/**\n * The builder → a `DocType` create body. Auto-derives `autoname`/`titleField` from\n * conventional fields when present (a `slug` field → `field:slug` naming; a `title`\n * field → the title). Tags the module so the collection joins the lane.\n */\nexport function toDocType(name: string, module: string, fields: BuilderField[]): DocType {\n const docFields = fields.map(toDocField)\n const byName = new Set(docFields.map((f) => f.fieldname))\n const dt: DocType = { name: name.trim(), module, fields: docFields }\n if (byName.has('slug')) dt.autoname = 'field:slug'\n if (byName.has('title')) dt.titleField = 'title'\n return dt\n}\n","/**\n * The DAM transport for a media DocType — as a PORT, not a binding. The library\n * knows the SHAPE of an object store (ensure a bucket, presign a PUT, presign a\n * GET, delete an object) and owns the key/reference grammar; the HOST supplies the\n * store. The console injects its org-scoped `/v1/s3` client (SeaweedFS); a native\n * app or a test injects something else. One media model, any storage.\n *\n * WHY STORE THE KEY, NOT A URL: a presigned object URL has a short TTL (the cloud\n * mints 5 minutes), and a stored presigned URL would break minutes later — fatal\n * for a media library whose references must persist. So the `file` field stores a\n * STABLE `s3://bucket/key` reference and every view resolves it to a fresh\n * presigned GET at render time. `isRef` keeps a legacy hand-typed absolute URL\n * working, so nothing that already exists breaks.\n */\nimport { slugify } from './fields'\nimport type { MediaFacts } from './fields'\n\n/** A presigned request the host's object store minted. */\nexport interface Presigned {\n url: string\n /** HTTP method the URL is signed for (upload must be `PUT`). */\n method?: string\n}\n\n/** The object-store seam a host injects. Every call is per-org on the host side. */\nexport interface MediaStore {\n /** Idempotent — an \"already exists\" is success, not an error. */\n ensureBucket: (bucket: string) => Promise<void>\n presignUpload: (bucket: string, key: string) => Promise<Presigned | null>\n presignDownload: (bucket: string, key: string) => Promise<Presigned | null>\n deleteObject: (bucket: string, key: string) => Promise<void>\n /** Transfer the bytes to a presigned URL. */\n put: (url: string, file: File) => Promise<void>\n}\n\n/** The prefix that marks a media `file` value as an object-store key (not a raw URL). */\nconst REF_PREFIX = 's3://'\n\n/** A bucket + stored object key → the `file`-field reference value. */\nexport function mediaRef(bucket: string, key: string): string {\n return `${REF_PREFIX}${bucket}/${key}`\n}\n\n/** True when a `file` value is an object reference (vs a hand-typed URL). */\nexport function isRef(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith(REF_PREFIX)\n}\n\n/** Split an `s3://bucket/key` reference into its bucket + key. */\nexport function parseRef(ref: string): { bucket: string; key: string } | null {\n if (!ref.startsWith(REF_PREFIX)) return null\n const rest = ref.slice(REF_PREFIX.length)\n const slash = rest.indexOf('/')\n if (slash <= 0) return null\n return { bucket: rest.slice(0, slash), key: rest.slice(slash + 1) }\n}\n\n/** Join a folder prefix and a name into an object key (blank segments dropped). */\nexport function joinKey(...parts: string[]): string {\n return parts.filter(Boolean).join('/')\n}\n\n/** A safe, collision-resistant object key for an uploaded file (keeps the ext). */\nexport function mediaKey(filename: string, folder = ''): string {\n const dot = filename.lastIndexOf('.')\n const ext = dot > 0 ? filename.slice(dot + 1).toLowerCase().replace(/[^a-z0-9]/g, '') : ''\n const base = slugify(dot > 0 ? filename.slice(0, dot) : filename) || 'file'\n const stamp = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`\n const name = ext ? `${base}-${stamp}.${ext}` : `${base}-${stamp}`\n return folder ? joinKey(slugify(folder), name) : name\n}\n\n/** True when a value looks like a renderable image (by extension / data URL). */\nexport function looksLikeImage(value: string): boolean {\n return /\\.(png|jpe?g|gif|webp|svg|avif)(\\?|#|$)/i.test(value) || value.startsWith('data:image/')\n}\n\n/** The three operations a media view needs, bound to one bucket. */\nexport interface MediaUploader {\n bucket: string\n /** Upload a file and return the facts a media document is built from. */\n upload: (file: File, folder?: string) => Promise<MediaFacts>\n /** A `file` value → a viewable URL ('' when it can't resolve — never a broken img). */\n resolveUrl: (value: unknown) => Promise<string>\n /** Delete the object behind a `file` value (a no-op for a plain URL). */\n remove: (value: unknown) => Promise<void>\n}\n\n/**\n * Bind the media operations to a host store + a bucket. The bucket is a PARAMETER\n * (not a constant named after one lane), so ERP attachments and Helpdesk files do\n * not land in a bucket called `cms-media`.\n */\nexport function createMediaUploader(store: MediaStore, bucket: string): MediaUploader {\n return {\n bucket,\n\n async upload(file, folder = '') {\n // 1) Ensure the per-org bucket. A create that fails because it already\n // exists is expected on every upload after the first.\n await store.ensureBucket(bucket).catch(() => undefined)\n\n // 2) Presign a PUT for a stable key, then upload the bytes directly.\n const key = mediaKey(file.name, folder)\n const presigned = await store.presignUpload(bucket, key)\n if (!presigned || (presigned.method ?? 'PUT') !== 'PUT' || !presigned.url) {\n throw new Error('Could not start the upload (object storage not configured).')\n }\n await store.put(presigned.url, file)\n\n // 3) Intrinsic image dimensions (best-effort; 0×0 for non-images / failures).\n const { width, height } = await imageDimensions(file)\n\n return {\n fileRef: mediaRef(bucket, key),\n filename: file.name,\n mime: file.type || 'application/octet-stream',\n size: file.size,\n width,\n height,\n }\n },\n\n async resolveUrl(value) {\n if (typeof value !== 'string' || value === '') return ''\n if (!isRef(value)) return value // a hand-typed absolute URL\n const parsed = parseRef(value)\n if (!parsed) return ''\n const presigned = await store.presignDownload(parsed.bucket, parsed.key).catch(() => null)\n return presigned?.url ?? ''\n },\n\n async remove(value) {\n if (!isRef(value)) return\n const parsed = parseRef(value)\n if (!parsed) return\n await store.deleteObject(parsed.bucket, parsed.key).catch(() => undefined)\n },\n }\n}\n\n/** Read an image file's intrinsic width/height in the browser (0×0 if not an image). */\nexport function imageDimensions(file: File): Promise<{ width: number; height: number }> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined' || typeof Image === 'undefined' || !file.type.startsWith('image/')) {\n resolve({ width: 0, height: 0 })\n return\n }\n const url = URL.createObjectURL(file)\n const img = new Image()\n img.onload = () => {\n resolve({ width: img.naturalWidth, height: img.naturalHeight })\n URL.revokeObjectURL(url)\n }\n img.onerror = () => {\n resolve({ width: 0, height: 0 })\n URL.revokeObjectURL(url)\n }\n img.src = url\n })\n}\n","/**\n * Shared, non-React data helpers for the generic DocType renderer. A relation\n * (Link) field is a picker over the TARGET doctype's records, so before a view\n * can render or edit one it must load those records (+ the target's schema for\n * the human label). This is the ONE place that does it, used by the records list,\n * the mobile card list and the record detail — no per-view duplication.\n */\nimport type { SelectOption, FieldDefinition } from '@hanzo/data'\nimport type { DocType } from './types'\nimport type { FrameworkClient } from './client'\nimport { linkFields, titleOf } from './fields'\n\n/** The picker options for every Link field of `dt`: value = target id, label = its title. */\nexport async function loadLinkOptions(\n client: FrameworkClient,\n dt: DocType,\n): Promise<Record<string, SelectOption[]>> {\n const links = linkFields(dt)\n const out: Record<string, SelectOption[]> = {}\n await Promise.all(\n links.map(async (f) => {\n const target = f.options\n if (!target) return\n // A target the caller can't read (403) → no options → the field falls back\n // to a raw-id input (honest, never a fabricated candidate list).\n const [tdt, docs] = await Promise.all([\n client.doctypes.get(target).catch(() => null),\n client.records.list(target, { limit: 200 }).catch(() => []),\n ])\n out[f.fieldname] = docs.map((d) => ({\n value: String(d.name),\n label: tdt ? titleOf(d, tdt) : String(d.name),\n }))\n }),\n )\n return out\n}\n\n/**\n * The `fieldOptions` callback @hanzo/data's views take: relation fields get their\n * loaded target records; select fields get the choices declared in metadata (so\n * the table cell and the form input agree). Everything else → undefined.\n */\nexport function makeFieldOptions(\n linkOptions: Record<string, SelectOption[]>,\n): (field: FieldDefinition) => SelectOption[] | undefined {\n return (field) => {\n if (field.type === 'relation') return linkOptions[field.name] ?? []\n if (field.type === 'select' || field.type === 'multiSelect') {\n return (field.metadata as { options?: SelectOption[] } | undefined)?.options\n }\n return undefined\n }\n}\n"]}
@@ -0,0 +1,343 @@
1
+ 'use client';
2
+ import { useEmit, labelOf } from './chunk-FVQXROBK.js';
3
+ import { YStack, XStack, Text, Theme, useThemeName, Portal, useControllableState, Button } from '@hanzo/gui';
4
+ import { Check, ChevronRight, ChevronDown } from '@hanzogui/lucide-icons-2';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { useRef, useState, useCallback, useLayoutEffect, useEffect } from 'react';
7
+
8
+ var ITEM_MIN_HEIGHT = 30;
9
+ var ITEM_RADIUS = 7;
10
+ var ITEM_PX = 8;
11
+ var ITEM_GAP = 8;
12
+ var ICON_SLOT = 16;
13
+ var PANEL_RADIUS = 12;
14
+ var PANEL_PAD = 4;
15
+ var PANEL_GAP = 2;
16
+ var SEP_MARGIN = 4;
17
+ var FONT_LABEL = 13;
18
+ var FONT_MUTED = 11;
19
+ var FONT_SHORTCUT = 12;
20
+ var ACCENT = "var(--hanzo-accent, #8b5cf6)";
21
+ var ACCENT_SOFT = "var(--hanzo-accent-soft, rgba(139,92,246,0.16))";
22
+ var DANGER = "var(--hanzo-danger, #ef4444)";
23
+ function MenuPanel({
24
+ children,
25
+ minWidth = 200,
26
+ maxHeight = 360,
27
+ onKeyDown,
28
+ panelRef,
29
+ ...rest
30
+ }) {
31
+ return /* @__PURE__ */ jsx(
32
+ YStack,
33
+ {
34
+ ref: panelRef,
35
+ role: "menu",
36
+ bg: "$color2",
37
+ borderColor: "$borderColor",
38
+ borderWidth: 1,
39
+ rounded: PANEL_RADIUS,
40
+ p: PANEL_PAD,
41
+ gap: PANEL_GAP,
42
+ minW: minWidth,
43
+ maxH: maxHeight,
44
+ overflow: "scroll",
45
+ shadowColor: "rgba(0,0,0,0.45)",
46
+ shadowRadius: 20,
47
+ shadowOffset: { width: 0, height: 10 },
48
+ onKeyDown,
49
+ ...rest,
50
+ children
51
+ }
52
+ );
53
+ }
54
+ function MenuItemView({
55
+ icon,
56
+ label,
57
+ description,
58
+ shortcut,
59
+ selected = false,
60
+ disabled = false,
61
+ destructive = false,
62
+ hasSubmenu = false,
63
+ onSelect
64
+ }) {
65
+ const track = useEmit();
66
+ const choose = () => {
67
+ track({ component: "MenuItem", action: "select", id: labelOf(label), value: selected });
68
+ onSelect();
69
+ };
70
+ const press = () => {
71
+ if (!disabled) choose();
72
+ };
73
+ const onKeyDown = (e) => {
74
+ if (disabled) return;
75
+ if (e.key === "Enter" || e.key === " ") {
76
+ e.preventDefault();
77
+ choose();
78
+ }
79
+ };
80
+ const labelColor = destructive ? DANGER : "$color12";
81
+ return /* @__PURE__ */ jsxs(
82
+ XStack,
83
+ {
84
+ role: "menuitem",
85
+ tabIndex: disabled ? -1 : 0,
86
+ "aria-disabled": disabled || void 0,
87
+ items: "center",
88
+ gap: ITEM_GAP,
89
+ px: ITEM_PX,
90
+ minH: ITEM_MIN_HEIGHT,
91
+ rounded: ITEM_RADIUS,
92
+ cursor: disabled ? "default" : "pointer",
93
+ opacity: disabled ? 0.4 : 1,
94
+ select: "none",
95
+ style: { outline: "none" },
96
+ hoverStyle: disabled ? {} : { bg: ACCENT_SOFT },
97
+ pressStyle: disabled ? {} : { bg: ACCENT_SOFT },
98
+ focusStyle: disabled ? {} : { bg: ACCENT_SOFT },
99
+ onPress: press,
100
+ onKeyDown,
101
+ children: [
102
+ /* @__PURE__ */ jsx(XStack, { width: ICON_SLOT, height: ICON_SLOT, items: "center", justify: "center", shrink: 0, children: icon ? /* @__PURE__ */ jsx(XStack, { items: "center", justify: "center", opacity: destructive ? 1 : 0.9, style: destructive ? { color: DANGER } : void 0, children: icon }) : null }),
103
+ /* @__PURE__ */ jsxs(YStack, { flex: 1, minW: 0, children: [
104
+ /* @__PURE__ */ jsx(Text, { fontSize: FONT_LABEL, lineHeight: 18, color: labelColor, numberOfLines: 1, children: label }),
105
+ description ? /* @__PURE__ */ jsx(Text, { fontSize: FONT_MUTED, lineHeight: 14, color: "$color11", numberOfLines: 1, children: description }) : null
106
+ ] }),
107
+ shortcut ? /* @__PURE__ */ jsx(Text, { fontSize: FONT_SHORTCUT, color: "$color11", shrink: 0, children: shortcut }) : null,
108
+ selected ? /* @__PURE__ */ jsx(Check, { size: 14, color: ACCENT }) : null,
109
+ hasSubmenu ? /* @__PURE__ */ jsx(ChevronRight, { size: 14, color: "var(--hanzo-muted, currentColor)", opacity: 0.6 }) : null
110
+ ]
111
+ }
112
+ );
113
+ }
114
+ function MenuSeparatorView() {
115
+ return /* @__PURE__ */ jsx(YStack, { height: 1, bg: "$borderColor", my: SEP_MARGIN, mx: SEP_MARGIN, role: "separator" });
116
+ }
117
+ function MenuLabelView({ children }) {
118
+ return /* @__PURE__ */ jsx(
119
+ Text,
120
+ {
121
+ fontSize: FONT_MUTED,
122
+ color: "$color11",
123
+ px: ITEM_PX,
124
+ py: SEP_MARGIN,
125
+ textTransform: "uppercase",
126
+ letterSpacing: 0.4,
127
+ select: "none",
128
+ children
129
+ }
130
+ );
131
+ }
132
+ function renderMenuItems(items, close) {
133
+ return items.map((it, i) => {
134
+ if (it.type === "separator") return /* @__PURE__ */ jsx(MenuSeparatorView, {}, it.key ?? `sep-${i}`);
135
+ if (it.type === "label") return /* @__PURE__ */ jsx(MenuLabelView, { children: it.label }, it.key ?? `lbl-${i}`);
136
+ const { key, onSelect, closeOnSelect = true, ...rest } = it;
137
+ return /* @__PURE__ */ jsx(
138
+ MenuItemView,
139
+ {
140
+ ...rest,
141
+ onSelect: () => {
142
+ onSelect();
143
+ if (closeOnSelect) close?.();
144
+ }
145
+ },
146
+ key
147
+ );
148
+ });
149
+ }
150
+ function PortalTheme({ name, children }) {
151
+ return /* @__PURE__ */ jsx(Theme, { name, children });
152
+ }
153
+
154
+ // src/product/menu/roving.ts
155
+ function menuKeyDown(e, onClose) {
156
+ if (e.key === "Escape") {
157
+ onClose?.();
158
+ return;
159
+ }
160
+ if (e.key !== "ArrowDown" && e.key !== "ArrowUp" && e.key !== "Home" && e.key !== "End") return;
161
+ if (typeof document === "undefined") return;
162
+ const panel = e.currentTarget;
163
+ const items = Array.from(
164
+ panel.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])')
165
+ );
166
+ if (items.length === 0) return;
167
+ e.preventDefault();
168
+ const active = document.activeElement;
169
+ const current = active ? items.indexOf(active) : -1;
170
+ let next;
171
+ if (e.key === "Home") next = 0;
172
+ else if (e.key === "End") next = items.length - 1;
173
+ else if (e.key === "ArrowDown") next = current < 0 ? 0 : (current + 1) % items.length;
174
+ else next = current <= 0 ? items.length - 1 : current - 1;
175
+ items[next]?.focus();
176
+ }
177
+ var EDGE = 8;
178
+ function FloatingMenu({
179
+ open,
180
+ onClose,
181
+ anchorRect,
182
+ anchorEl,
183
+ gap = 4,
184
+ minWidth = 200,
185
+ maxHeight,
186
+ autoFocus = true,
187
+ children
188
+ }) {
189
+ const themeName = useThemeName();
190
+ const panelRef = useRef(null);
191
+ const [pos, setPos] = useState(null);
192
+ const setPanel = useCallback((n) => {
193
+ panelRef.current = n;
194
+ }, []);
195
+ const place = useCallback(() => {
196
+ if (typeof window === "undefined") return;
197
+ const a = anchorRect();
198
+ if (!a) return;
199
+ const node = panelRef.current;
200
+ const w = node?.offsetWidth || minWidth;
201
+ const h = node?.offsetHeight || 0;
202
+ let left = a.left;
203
+ let top = a.bottom + gap;
204
+ if (left + w > window.innerWidth - EDGE) left = Math.max(EDGE, window.innerWidth - w - EDGE);
205
+ if (h && top + h > window.innerHeight - EDGE) {
206
+ const above = a.top - gap - h;
207
+ top = above >= EDGE ? above : Math.max(EDGE, window.innerHeight - h - EDGE);
208
+ }
209
+ setPos({ left, top });
210
+ }, [anchorRect, gap, minWidth]);
211
+ useLayoutEffect(() => {
212
+ if (!open) {
213
+ setPos(null);
214
+ return;
215
+ }
216
+ place();
217
+ if (autoFocus) panelRef.current?.focus?.();
218
+ }, [open, place, autoFocus]);
219
+ useEffect(() => {
220
+ if (!open || typeof document === "undefined") return;
221
+ const onPointerDown = (e) => {
222
+ const t = e.target;
223
+ if (panelRef.current?.contains(t)) return;
224
+ const anchor = anchorEl?.();
225
+ if (anchor && anchor.contains(t)) return;
226
+ onClose();
227
+ };
228
+ const onKey = (e) => {
229
+ if (e.key === "Escape") onClose();
230
+ };
231
+ document.addEventListener("pointerdown", onPointerDown, true);
232
+ document.addEventListener("keydown", onKey, true);
233
+ window.addEventListener("scroll", onClose, true);
234
+ window.addEventListener("resize", onClose);
235
+ window.addEventListener("blur", onClose);
236
+ return () => {
237
+ document.removeEventListener("pointerdown", onPointerDown, true);
238
+ document.removeEventListener("keydown", onKey, true);
239
+ window.removeEventListener("scroll", onClose, true);
240
+ window.removeEventListener("resize", onClose);
241
+ window.removeEventListener("blur", onClose);
242
+ };
243
+ }, [open, onClose, anchorEl]);
244
+ if (!open) return null;
245
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(PortalTheme, { name: themeName, children: /* @__PURE__ */ jsx(
246
+ MenuPanel,
247
+ {
248
+ panelRef: setPanel,
249
+ minWidth,
250
+ maxHeight,
251
+ tabIndex: -1,
252
+ onKeyDown: (e) => menuKeyDown(e, onClose),
253
+ style: {
254
+ position: "fixed",
255
+ left: pos?.left ?? 0,
256
+ top: pos?.top ?? 0,
257
+ zIndex: 1e5,
258
+ visibility: pos ? "visible" : "hidden"
259
+ },
260
+ children
261
+ }
262
+ ) }) });
263
+ }
264
+ function DropdownMenu({
265
+ trigger,
266
+ items,
267
+ open,
268
+ defaultOpen = false,
269
+ onOpenChange,
270
+ minWidth = 200,
271
+ maxHeight
272
+ }) {
273
+ const [isOpen, setOpen] = useControllableState({
274
+ prop: open,
275
+ defaultProp: defaultOpen,
276
+ onChange: onOpenChange
277
+ });
278
+ const anchorRef = useRef(null);
279
+ const anchorRect = useCallback(() => anchorRef.current?.getBoundingClientRect() ?? null, []);
280
+ const anchorEl = useCallback(() => anchorRef.current, []);
281
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
282
+ /* @__PURE__ */ jsx(XStack, { ref: anchorRef, self: "flex-start", cursor: "pointer", onPress: () => setOpen(!isOpen), children: trigger }),
283
+ /* @__PURE__ */ jsx(
284
+ FloatingMenu,
285
+ {
286
+ open: isOpen,
287
+ onClose: () => setOpen(false),
288
+ anchorRect,
289
+ anchorEl,
290
+ minWidth,
291
+ maxHeight,
292
+ children: renderMenuItems(items, () => setOpen(false))
293
+ }
294
+ )
295
+ ] });
296
+ }
297
+ function SelectMenu({
298
+ options,
299
+ value,
300
+ onChange,
301
+ allLabel = "All",
302
+ icon,
303
+ minWidth = 130,
304
+ required,
305
+ minHeight,
306
+ disabled,
307
+ ariaLabel
308
+ }) {
309
+ const active = value === null ? null : options.find((o) => o.key === value) ?? null;
310
+ const triggerLabel = active ? active.label : allLabel;
311
+ const items = [
312
+ ...required ? [] : [{ key: "__all__", label: allLabel, selected: value === null, onSelect: () => onChange(null) }],
313
+ ...options.map((o) => ({ key: o.key, label: o.label, selected: value === o.key, onSelect: () => onChange(o.key) }))
314
+ ];
315
+ return /* @__PURE__ */ jsx(
316
+ DropdownMenu,
317
+ {
318
+ minWidth: Math.max(minWidth, 160),
319
+ trigger: /* @__PURE__ */ jsx(
320
+ Button,
321
+ {
322
+ size: minHeight && minHeight >= 40 ? "$4" : "$2",
323
+ minW: minWidth,
324
+ minH: minHeight,
325
+ disabled,
326
+ "aria-label": ariaLabel,
327
+ justify: "space-between",
328
+ borderWidth: 1,
329
+ borderColor: "$borderColor",
330
+ bg: !required && value !== null ? "$color5" : "transparent",
331
+ icon,
332
+ iconAfter: /* @__PURE__ */ jsx(ChevronDown, { size: 14, opacity: 0.6 }),
333
+ children: /* @__PURE__ */ jsx(Text, { fontSize: "$2", color: "$color12", numberOfLines: 1, flex: 1, children: triggerLabel })
334
+ }
335
+ ),
336
+ items
337
+ }
338
+ );
339
+ }
340
+
341
+ export { DropdownMenu, FloatingMenu, MenuItemView, MenuLabelView, MenuPanel, MenuSeparatorView, PortalTheme, SelectMenu, renderMenuItems };
342
+ //# sourceMappingURL=chunk-5CZOYONP.js.map
343
+ //# sourceMappingURL=chunk-5CZOYONP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/product/menu/items.tsx","../src/product/menu/portal-theme.tsx","../src/product/menu/roving.ts","../src/product/menu/FloatingMenu.tsx","../src/product/menu/DropdownMenu.tsx","../src/product/SelectMenu.tsx"],"names":["jsx","useRef","useCallback","jsxs","XStack","Text"],"mappings":"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","file":"chunk-5CZOYONP.js","sourcesContent":["'use client'\n\n/**\n * The ONE menu-item spec — every menu across the fleet renders through these\n * presentational primitives, so DropdownMenu, ContextMenu, SelectMenu and ComboBox\n * are pixel-identical. Geometry is literal px on a strict 8-grid (never random);\n * colour is theme-adaptive tokens ($color2/$color11/$color12/$borderColor) so light\n * and dark both work, with the single purple accent supplied by the brand CSS vars.\n *\n * Style props use the @hanzo/gui config shorthands (bg/items/justify/px/py/p/mx/my/\n * minW/maxH/rounded/select/shrink) — the config omits the longhand aliases.\n *\n * Panel — bg $color2 (#111 dark), hairline border, radius 12, inner pad 4, subtle\n * border+ambient elevation.\n * Item — height 30 (28–32 band), px 8, gap 8, radius 7; icon in a fixed 16px slot\n * on the left; label 13px $color12; right affordance (shortcut / check /\n * chevron) right-aligned. States: hover/active/focus → accent-soft, focus\n * visible; selected → check + purple; disabled → muted, no hover.\n * Separator — 1px hairline, 4px vertical margin.\n * Label — 11px uppercase muted section header, px 8.\n */\nimport type { ReactNode, KeyboardEvent } from 'react'\nimport { Text, XStack, YStack } from '@hanzo/gui'\nimport { Check, ChevronRight } from '@hanzogui/lucide-icons-2'\n\n// ── Geometry — literal px, 8-grid ──────────────────────────────────────────────\nconst ITEM_MIN_HEIGHT = 30\nconst ITEM_RADIUS = 7\nconst ITEM_PX = 8\nconst ITEM_GAP = 8\nconst ICON_SLOT = 16\nexport const PANEL_RADIUS = 12\nexport const PANEL_PAD = 4\nconst PANEL_GAP = 2\nconst SEP_MARGIN = 4\nconst FONT_LABEL = 13\nconst FONT_MUTED = 11\nconst FONT_SHORTCUT = 12\n\n// ── Colour — brand purple accent via CSS vars (fallbacks keep it correct even when\n// @hanzo/brand is not loaded, e.g. a bare Vite/Tauri host); everything else uses\n// theme-adaptive Tamagui tokens. ──────────────────────────────────────────────\nconst ACCENT = 'var(--hanzo-accent, #8b5cf6)'\nconst ACCENT_SOFT = 'var(--hanzo-accent-soft, rgba(139,92,246,0.16))'\nconst DANGER = 'var(--hanzo-danger, #ef4444)'\n\n// ── Declarative item model ──────────────────────────────────────────────────────\nexport type MenuItemSpec =\n | {\n type?: 'item'\n /** Stable key. */\n key: string\n label: string\n /** Leading Lucide icon (16px, unfilled) in the fixed left slot. */\n icon?: ReactNode\n /** Second muted line under the label (e.g. an id or hint). */\n description?: string\n /** Right-aligned shortcut / hint text (e.g. \"⌘K\"). */\n shortcut?: string\n /** Renders a right check + purple tint. */\n selected?: boolean\n disabled?: boolean\n /** Danger styling (red label/icon). */\n destructive?: boolean\n /** Renders a right chevron (submenu / drill-in affordance). */\n hasSubmenu?: boolean\n onSelect: () => void\n /** Keep the menu open after selecting (default: close). */\n closeOnSelect?: boolean\n }\n | { type: 'separator'; key?: string }\n | { type: 'label'; key?: string; label: string }\n\n// ── Surface ───────────────────────────────────────────────────────────────────\nexport function MenuPanel({\n children,\n minWidth = 200,\n maxHeight = 360,\n onKeyDown,\n panelRef,\n ...rest\n}: {\n children: ReactNode\n minWidth?: number\n maxHeight?: number\n onKeyDown?: (e: KeyboardEvent) => void\n /** Web DOM node of the panel (for measuring / edge-flip). */\n panelRef?: (node: HTMLElement | null) => void\n [key: string]: unknown\n}) {\n return (\n <YStack\n // Web DOM ref; Gui forwards it to the underlying node. Cast (not @ts-expect-error)\n // so it is env-agnostic — the ref type is strict under the pkg build, loose here.\n ref={panelRef as never}\n role=\"menu\"\n bg=\"$color2\"\n borderColor=\"$borderColor\"\n borderWidth={1}\n rounded={PANEL_RADIUS}\n p={PANEL_PAD}\n gap={PANEL_GAP}\n minW={minWidth}\n maxH={maxHeight}\n overflow=\"scroll\"\n // Subtle border + ambient elevation, minimal shadow.\n shadowColor=\"rgba(0,0,0,0.45)\"\n shadowRadius={20}\n shadowOffset={{ width: 0, height: 10 }}\n onKeyDown={onKeyDown as never}\n {...rest}\n >\n {children}\n </YStack>\n )\n}\n\n// ── Item — the ONE row ──────────────────────────────────────────────────────────\nimport { labelOf, useEmit } from '../instrument'\n\nexport function MenuItemView({\n icon,\n label,\n description,\n shortcut,\n selected = false,\n disabled = false,\n destructive = false,\n hasSubmenu = false,\n onSelect,\n}: Omit<Extract<MenuItemSpec, { type?: 'item' }>, 'key' | 'type' | 'closeOnSelect'>) {\n const track = useEmit()\n const choose = () => {\n track({ component: 'MenuItem', action: 'select', id: labelOf(label), value: selected })\n onSelect()\n }\n const press = () => {\n if (!disabled) choose()\n }\n const onKeyDown = (e: KeyboardEvent) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n choose()\n }\n }\n const labelColor = destructive ? DANGER : '$color12'\n return (\n <XStack\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled || undefined}\n items=\"center\"\n gap={ITEM_GAP}\n px={ITEM_PX}\n minH={ITEM_MIN_HEIGHT}\n rounded={ITEM_RADIUS}\n cursor={disabled ? 'default' : 'pointer'}\n opacity={disabled ? 0.4 : 1}\n select=\"none\"\n style={{ outline: 'none' }}\n hoverStyle={disabled ? {} : { bg: ACCENT_SOFT as never }}\n pressStyle={disabled ? {} : { bg: ACCENT_SOFT as never }}\n focusStyle={disabled ? {} : { bg: ACCENT_SOFT as never }}\n onPress={press}\n onKeyDown={onKeyDown as never}\n >\n <XStack width={ICON_SLOT} height={ICON_SLOT} items=\"center\" justify=\"center\" shrink={0}>\n {icon ? (\n <XStack items=\"center\" justify=\"center\" opacity={destructive ? 1 : 0.9} style={destructive ? { color: DANGER } : undefined}>\n {icon}\n </XStack>\n ) : null}\n </XStack>\n\n <YStack flex={1} minW={0}>\n <Text fontSize={FONT_LABEL} lineHeight={18} color={labelColor as never} numberOfLines={1}>\n {label}\n </Text>\n {description ? (\n <Text fontSize={FONT_MUTED} lineHeight={14} color=\"$color11\" numberOfLines={1}>\n {description}\n </Text>\n ) : null}\n </YStack>\n\n {shortcut ? (\n <Text fontSize={FONT_SHORTCUT} color=\"$color11\" shrink={0}>\n {shortcut}\n </Text>\n ) : null}\n {selected ? <Check size={14} color={ACCENT} /> : null}\n {hasSubmenu ? <ChevronRight size={14} color=\"var(--hanzo-muted, currentColor)\" opacity={0.6} /> : null}\n </XStack>\n )\n}\n\n// ── Separator ───────────────────────────────────────────────────────────────────\nexport function MenuSeparatorView() {\n return <YStack height={1} bg=\"$borderColor\" my={SEP_MARGIN} mx={SEP_MARGIN} role=\"separator\" />\n}\n\n// ── Section label ────────────────────────────────────────────────────────────────\nexport function MenuLabelView({ children }: { children: ReactNode }) {\n return (\n <Text\n fontSize={FONT_MUTED}\n color=\"$color11\"\n px={ITEM_PX}\n py={SEP_MARGIN}\n textTransform=\"uppercase\"\n letterSpacing={0.4}\n select=\"none\"\n >\n {children}\n </Text>\n )\n}\n\n// ── The single render path shared by every menu ──────────────────────────────────\nexport function renderMenuItems(items: MenuItemSpec[], close?: () => void): ReactNode {\n return items.map((it, i) => {\n if (it.type === 'separator') return <MenuSeparatorView key={it.key ?? `sep-${i}`} />\n if (it.type === 'label') return <MenuLabelView key={it.key ?? `lbl-${i}`}>{it.label}</MenuLabelView>\n const { key, onSelect, closeOnSelect = true, ...rest } = it\n return (\n <MenuItemView\n key={key}\n {...rest}\n onSelect={() => {\n onSelect()\n if (closeOnSelect) close?.()\n }}\n />\n )\n })\n}\n","'use client'\n\n/**\n * PortalTheme — the ONE fix for \"themed content escapes its theme through a portal\".\n *\n * @hanzo/gui's `Popover.Content` and `Portal` render their children in a SEPARATE\n * React subtree (a Gorhom-style portal host mounted at the app root), NOT via\n * `ReactDOM.createPortal`. React context therefore does NOT flow from the trigger's\n * location to the host. Under a nested `<Theme name=\"dark\">` the portaled content\n * lands OUTSIDE that theme context and Tamagui throws \"Missing theme\" (or renders\n * unthemed).\n *\n * The fix is two-part and must stay two-part:\n * 1. At the TRIGGER site (theme context still available) capture the resolved\n * theme name with `useThemeName()`.\n * 2. INSIDE the portaled content re-apply it: `<PortalTheme name={captured}>`.\n *\n * Every portal-backed menu in this package (DropdownMenu, ContextMenu, SelectMenu,\n * ComboBox) uses this so a menu renders identically whether it is opened under the\n * root theme or under any nested `<Theme>`, light or dark.\n */\nimport type { ReactNode } from 'react'\nimport { Theme, useThemeName } from '@hanzo/gui'\n\n/** Capture the current resolved theme name at the trigger site. Re-exported so the\n * capture + re-apply pair reads from one module. */\nexport { useThemeName }\n\nexport function PortalTheme({ name, children }: { name: string; children: ReactNode }) {\n // `name` is the resolved theme name (e.g. \"dark\", or a compound \"dark_purple\").\n // Tamagui's `Theme` accepts the resolved name and reconstructs the context.\n return <Theme name={name as never}>{children}</Theme>\n}\n","'use client'\n\n/**\n * Roving keyboard focus for a menu panel — ArrowUp/Down move focus between enabled\n * `[role=\"menuitem\"]` children, Home/End jump to ends, Escape closes. Web/desktop\n * only (guards on `document`); native menus have no pointer-keyboard nav. Shared by\n * DropdownMenu and ContextMenu so navigation is identical.\n */\nimport type { KeyboardEvent } from 'react'\n\nexport function menuKeyDown(e: KeyboardEvent, onClose?: () => void): void {\n if (e.key === 'Escape') {\n onClose?.()\n return\n }\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return\n if (typeof document === 'undefined') return\n\n const panel = e.currentTarget as HTMLElement\n const items = Array.from(\n panel.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])'),\n )\n if (items.length === 0) return\n e.preventDefault()\n\n const active = document.activeElement as HTMLElement | null\n const current = active ? items.indexOf(active) : -1\n let next: number\n if (e.key === 'Home') next = 0\n else if (e.key === 'End') next = items.length - 1\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % items.length\n else next = current <= 0 ? items.length - 1 : current - 1\n items[next]?.focus()\n}\n","'use client'\n\n/**\n * FloatingMenu — the ONE floating-panel mechanism for every menu. Renders the shared\n * MenuPanel through the @hanzo/gui Portal, positioned at an anchor (a trigger rect or a\n * cursor point), theme-forwarded via PortalTheme, edge-flipped, dismiss-wired and\n * keyboard-navigable.\n *\n * Why Portal, not gui Popover: gui's Popover pulls in a SheetController that re-roots the\n * trigger subtree and reads the theme from React context — on gui-native hosts\n * (react-native-web-lite, theme in context, no CSS-class fallback) that throws\n * \"Missing theme\" AT MOUNT. The raw Portal does not re-root, so DropdownMenu, ContextMenu,\n * SelectMenu and ComboBox all ride this ONE working path.\n */\nimport type { ReactNode, KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { Portal } from '@hanzo/gui'\nimport { MenuPanel } from './items'\nimport { PortalTheme, useThemeName } from './portal-theme'\nimport { menuKeyDown } from './roving'\n\nconst EDGE = 8\n\nexport type RectLike = { left: number; top: number; right: number; bottom: number; width: number; height: number }\n\nexport function FloatingMenu({\n open,\n onClose,\n anchorRect,\n anchorEl,\n gap = 4,\n minWidth = 200,\n maxHeight,\n autoFocus = true,\n children,\n}: {\n open: boolean\n onClose: () => void\n /** Anchor in viewport coords — a trigger's rect, or a zero-size rect at a cursor point. */\n anchorRect: () => RectLike | null | undefined\n /** Element excluded from outside-dismiss (the trigger / input row). */\n anchorEl?: () => HTMLElement | null | undefined\n /** Space between the anchor's bottom and the panel (0 for a cursor menu). */\n gap?: number\n minWidth?: number\n maxHeight?: number\n /** Focus the panel on open (for roving keys). ComboBox keeps focus in its input. */\n autoFocus?: boolean\n children: ReactNode\n}) {\n const themeName = useThemeName()\n const panelRef = useRef<HTMLElement | null>(null)\n const [pos, setPos] = useState<{ left: number; top: number } | null>(null)\n\n const setPanel = useCallback((n: HTMLElement | null) => {\n panelRef.current = n\n }, [])\n\n const place = useCallback(() => {\n if (typeof window === 'undefined') return\n const a = anchorRect()\n if (!a) return\n const node = panelRef.current\n const w = node?.offsetWidth || minWidth\n const h = node?.offsetHeight || 0\n let left = a.left\n let top = a.bottom + gap\n if (left + w > window.innerWidth - EDGE) left = Math.max(EDGE, window.innerWidth - w - EDGE)\n if (h && top + h > window.innerHeight - EDGE) {\n const above = a.top - gap - h\n top = above >= EDGE ? above : Math.max(EDGE, window.innerHeight - h - EDGE)\n }\n setPos({ left, top })\n }, [anchorRect, gap, minWidth])\n\n // Measure + position before paint; focus the panel for keyboard nav.\n useLayoutEffect(() => {\n if (!open) {\n setPos(null)\n return\n }\n place()\n if (autoFocus) panelRef.current?.focus?.()\n }, [open, place, autoFocus])\n\n // Dismiss on outside pointer (excluding the anchor), Escape, scroll, resize, blur.\n useEffect(() => {\n if (!open || typeof document === 'undefined') return\n const onPointerDown = (e: PointerEvent) => {\n const t = e.target as Node\n if (panelRef.current?.contains(t)) return\n const anchor = anchorEl?.()\n if (anchor && anchor.contains(t)) return\n onClose()\n }\n const onKey = (e: globalThis.KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKey, true)\n window.addEventListener('scroll', onClose, true)\n window.addEventListener('resize', onClose)\n window.addEventListener('blur', onClose)\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKey, true)\n window.removeEventListener('scroll', onClose, true)\n window.removeEventListener('resize', onClose)\n window.removeEventListener('blur', onClose)\n }\n }, [open, onClose, anchorEl])\n\n if (!open) return null\n return (\n <Portal>\n <PortalTheme name={themeName}>\n <MenuPanel\n panelRef={setPanel}\n minWidth={minWidth}\n maxHeight={maxHeight}\n tabIndex={-1}\n onKeyDown={(e: ReactKeyboardEvent) => menuKeyDown(e, onClose)}\n style={{\n position: 'fixed',\n left: pos?.left ?? 0,\n top: pos?.top ?? 0,\n zIndex: 100000,\n visibility: pos ? 'visible' : 'hidden',\n }}\n >\n {children}\n </MenuPanel>\n </PortalTheme>\n </Portal>\n )\n}\n","'use client'\n\n/**\n * DropdownMenu — a portal-theme-safe click menu. Declarative `items` rendered through the\n * ONE shared menu-item spec, so it is pixel-identical to ContextMenu/SelectMenu/ComboBox.\n * Built on FloatingMenu (gui Portal), NOT the gui Popover — so it mounts without the\n * Sheet re-root that loses theme context on gui-native hosts (react-native-web-lite).\n *\n * <DropdownMenu\n * trigger={<Button>Actions</Button>}\n * items={[\n * { key: 'rename', label: 'Rename', icon: <Pencil size={16} />, onSelect: rename },\n * { type: 'separator' },\n * { key: 'del', label: 'Delete', destructive: true, onSelect: del },\n * ]}\n * />\n */\nimport type { ReactElement } from 'react'\nimport { useCallback, useRef } from 'react'\nimport { XStack, useControllableState } from '@hanzo/gui'\nimport { renderMenuItems, type MenuItemSpec } from './items'\nimport { FloatingMenu } from './FloatingMenu'\n\nexport type DropdownMenuProps = {\n /** The clickable element. Wrapped so any element opens the menu on press. */\n trigger: ReactElement\n items: MenuItemSpec[]\n /** Controlled open state. Omit for uncontrolled. */\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n minWidth?: number\n maxHeight?: number\n}\n\nexport function DropdownMenu({\n trigger,\n items,\n open,\n defaultOpen = false,\n onOpenChange,\n minWidth = 200,\n maxHeight,\n}: DropdownMenuProps) {\n const [isOpen, setOpen] = useControllableState({\n prop: open,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n })\n const anchorRef = useRef<HTMLElement | null>(null)\n const anchorRect = useCallback(() => anchorRef.current?.getBoundingClientRect() ?? null, [])\n const anchorEl = useCallback(() => anchorRef.current, [])\n\n return (\n <>\n <XStack ref={anchorRef as never} self=\"flex-start\" cursor=\"pointer\" onPress={() => setOpen(!isOpen)}>\n {trigger}\n </XStack>\n <FloatingMenu\n open={isOpen}\n onClose={() => setOpen(false)}\n anchorRect={anchorRect}\n anchorEl={anchorEl}\n minWidth={minWidth}\n maxHeight={maxHeight}\n >\n {renderMenuItems(items, () => setOpen(false))}\n </FloatingMenu>\n </>\n )\n}\n","'use client'\n\n/**\n * SelectMenu — a compact, reusable dropdown select. Renders a labelled trigger (\"All\n * types\", or the chosen option) and a menu list with a check on the active option.\n * Prop-driven + self-contained. `value === null` is the \"all\"/unfiltered state.\n *\n * `required` turns the same control into a \"pick exactly one of N\": the null row is\n * dropped and the value is never nullable. That is the SAME control, not a second\n * one — a required field picker and a filter differ only in whether \"none\" is an\n * option, so it stays one component rather than growing a fourth select.\n *\n * A thin DropdownMenu (the ONE menu mechanism) so it is pixel-identical to every other\n * menu and rides the same portal-theme-safe Portal path — no gui Popover, no Sheet\n * re-root, works on gui-native hosts.\n */\nimport type { ReactElement } from 'react'\nimport { Button, Text } from '@hanzo/gui'\nimport { ChevronDown } from '@hanzogui/lucide-icons-2'\nimport { DropdownMenu } from './menu/DropdownMenu'\nimport type { MenuItemSpec } from './menu/items'\n\nexport type SelectOption<T extends string> = { key: T; label: string }\n\nexport function SelectMenu<T extends string>({\n options,\n value,\n onChange,\n allLabel = 'All',\n icon,\n minWidth = 130,\n required,\n minHeight,\n disabled,\n ariaLabel,\n}: {\n options: SelectOption<T>[]\n value: T | null\n onChange: (v: T | null) => void\n /** Label shown (and first menu row) for the unfiltered `null` state. */\n allLabel?: string\n /** Optional leading icon in the trigger. */\n icon?: ReactElement\n minWidth?: number\n /** Exactly one of `options` is always chosen — no \"all\"/none row. */\n required?: boolean\n /** Trigger height floor — pass the 44px tap floor on a phone. */\n minHeight?: number\n disabled?: boolean\n /** Accessible name for an unlabelled trigger. */\n ariaLabel?: string\n}) {\n const active = value === null ? null : options.find((o) => o.key === value) ?? null\n const triggerLabel = active ? active.label : allLabel\n\n const items: MenuItemSpec[] = [\n ...(required\n ? []\n : [{ key: '__all__', label: allLabel, selected: value === null, onSelect: () => onChange(null) }]),\n ...options.map((o) => ({ key: o.key, label: o.label, selected: value === o.key, onSelect: () => onChange(o.key) })),\n ]\n\n return (\n <DropdownMenu\n minWidth={Math.max(minWidth, 160)}\n trigger={\n <Button\n size={minHeight && minHeight >= 40 ? '$4' : '$2'}\n minW={minWidth}\n minH={minHeight}\n disabled={disabled}\n aria-label={ariaLabel}\n justify=\"space-between\"\n borderWidth={1}\n borderColor=\"$borderColor\"\n bg={!required && value !== null ? '$color5' : 'transparent'}\n icon={icon}\n iconAfter={<ChevronDown size={14} opacity={0.6} />}\n >\n <Text fontSize=\"$2\" color=\"$color12\" numberOfLines={1} flex={1}>\n {triggerLabel}\n </Text>\n </Button>\n }\n items={items}\n />\n )\n}\n"]}