@aglyn/aglyn 1.0.0-beta.268 → 1.0.0-beta.270

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 (82) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/account-preferences.d.ts +248 -0
  3. package/src/lib/app-utils/account-preferences.js +434 -0
  4. package/src/lib/app-utils/account-preferences.js.map +1 -0
  5. package/src/lib/app-utils/country-options.d.ts +27 -0
  6. package/src/lib/app-utils/country-options.js +96 -0
  7. package/src/lib/app-utils/country-options.js.map +1 -0
  8. package/src/lib/app-utils/docs-help.generated.d.ts +6 -0
  9. package/src/lib/app-utils/docs-help.generated.js +13 -0
  10. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  11. package/src/lib/app-utils/docs-index.generated.js +17 -10
  12. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  13. package/src/lib/app-utils/element-motion.d.ts +14 -2
  14. package/src/lib/app-utils/element-motion.js +33 -13
  15. package/src/lib/app-utils/element-motion.js.map +1 -1
  16. package/src/lib/app-utils/mobile-push.d.ts +8 -0
  17. package/src/lib/app-utils/mobile-push.js +4 -1
  18. package/src/lib/app-utils/mobile-push.js.map +1 -1
  19. package/src/lib/app-utils/native-app-association.d.ts +3 -2
  20. package/src/lib/app-utils/native-app-association.js +4 -2
  21. package/src/lib/app-utils/native-app-association.js.map +1 -1
  22. package/src/lib/app-utils/native-nav.d.ts +265 -0
  23. package/src/lib/app-utils/native-nav.js +741 -0
  24. package/src/lib/app-utils/native-nav.js.map +1 -0
  25. package/src/lib/app-utils/native-themes.d.ts +249 -0
  26. package/src/lib/app-utils/native-themes.js +732 -0
  27. package/src/lib/app-utils/native-themes.js.map +1 -0
  28. package/src/lib/app-utils/notifications.d.ts +1 -1
  29. package/src/lib/app-utils/notifications.js +10 -0
  30. package/src/lib/app-utils/notifications.js.map +1 -1
  31. package/src/lib/app-utils/one-box-search.d.ts +108 -0
  32. package/src/lib/app-utils/one-box-search.js +167 -0
  33. package/src/lib/app-utils/one-box-search.js.map +1 -0
  34. package/src/lib/app-utils/org-permissions.js +10 -61
  35. package/src/lib/app-utils/org-permissions.js.map +1 -1
  36. package/src/lib/app-utils/org-role-grants.d.ts +95 -0
  37. package/src/lib/app-utils/org-role-grants.js +193 -0
  38. package/src/lib/app-utils/org-role-grants.js.map +1 -0
  39. package/src/lib/app-utils/plan-entitlements.d.ts +41 -1
  40. package/src/lib/app-utils/plan-entitlements.js +65 -3
  41. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  42. package/src/lib/app-utils/tenant-dns-targets.d.ts +62 -0
  43. package/src/lib/app-utils/tenant-dns-targets.js +80 -0
  44. package/src/lib/app-utils/tenant-dns-targets.js.map +1 -0
  45. package/src/lib/foundation/definitions/org-billing.types.d.ts +14 -0
  46. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  47. package/src/lib/foundation/definitions/platform.types.d.ts +9 -0
  48. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  49. package/src/lib/plugin-manager/feature-plugins.d.ts +38 -0
  50. package/src/lib/plugin-manager/feature-plugins.js +20 -0
  51. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  52. package/src/lib/plugin-manager/first-party-plugins.generated.js +22 -1
  53. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  54. package/src/lib/plugin-manager/operator-alerts.js +10 -1
  55. package/src/lib/plugin-manager/operator-alerts.js.map +1 -1
  56. package/src/lib/plugin-manager/plugin-config.js +10 -1
  57. package/src/lib/plugin-manager/plugin-config.js.map +1 -1
  58. package/src/lib/plugin-manager/plugin-consent-group-change.js +11 -2
  59. package/src/lib/plugin-manager/plugin-consent-group-change.js.map +1 -1
  60. package/src/lib/plugin-manager/plugin-console-crons.js +10 -1
  61. package/src/lib/plugin-manager/plugin-console-crons.js.map +1 -1
  62. package/src/lib/plugin-manager/plugin-domain-events.d.ts +4 -3
  63. package/src/lib/plugin-manager/plugin-domain-events.js.map +1 -1
  64. package/src/lib/plugin-manager/plugin-events.js +11 -2
  65. package/src/lib/plugin-manager/plugin-events.js.map +1 -1
  66. package/src/lib/plugin-manager/plugin-lead-conversion.js +10 -1
  67. package/src/lib/plugin-manager/plugin-lead-conversion.js.map +1 -1
  68. package/src/lib/plugin-manager/plugin-media-ingest.d.ts +25 -0
  69. package/src/lib/plugin-manager/plugin-media-ingest.js.map +1 -1
  70. package/src/lib/plugin-manager/plugin-membership-detach.js +10 -1
  71. package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
  72. package/src/lib/plugin-manager/plugin-person-matches.js +10 -1
  73. package/src/lib/plugin-manager/plugin-person-matches.js.map +1 -1
  74. package/src/lib/plugin-manager/plugin-search-sources.d.ts +85 -0
  75. package/src/lib/plugin-manager/plugin-search-sources.js +91 -0
  76. package/src/lib/plugin-manager/plugin-search-sources.js.map +1 -0
  77. package/src/lib/plugin-manager/plugin-services.js +6 -0
  78. package/src/lib/plugin-manager/plugin-services.js.map +1 -1
  79. package/src/lib/plugin-manager/plugin-usage-meters.js +10 -1
  80. package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -1
  81. package/src/lib/plugin-manager/usage-alert-contributors.js +10 -1
  82. package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/native-nav.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * THE NATIVE APPS' NAVIGATION, AS DATA (AGL-3943).\n *\n * One manifest both shells draw (docs/mobile/native-navigation.md): the\n * sidebar for the whole workspace, the sidebar inside one site, and the two\n * settings modes (the workspace's, and the site's, which merges the\n * console's Setup and Admin). Zach chose the site's groups on 2026-10-18:\n * an Overview row, Starred, Website, Sell, Customers, More, Site settings.\n *\n * Every row names:\n * - the console's word for it (`label`), held to the console by\n * `apps/console/specs/native-nav-manifest.spec.ts`, which reads the\n * console's own tabs, sections and plugin declarations;\n * - one icon per idea, an SF Symbol and a Material Symbol;\n * - the native screen it opens (a plugin's declared screen, a core screen\n * spec, a site platform screen or a `shell.*` destination);\n * - the plugin it belongs to, so it hides when that plugin is off for the\n * workspace or the site.\n *\n * The core's own rows (Home, Overview, Sites, Pages, Media, the settings\n * modes) are here; a plugin's rows are its own, in\n * `libs/plugins/<plugin>/src/lib/native-nav.ts` (`NATIVE_NAV_ROWS`), placed\n * into a list's group by `order` (docs/PACKAGES.md rule 3: the core never\n * names a plugin). `generate:native-contracts` assembles the two\n * (`assembleNativeNav`) into the manifest the apps read,\n * `ContractValues.nativeNavManifest`.\n *\n * NO IMPORTS, on purpose: the native apps read this through the generated\n * contracts, so it must stay a plain module.\n */\n\n/** A list the shells draw. */\nexport type NativeNavListId = 'workspace' | 'site' | 'workspaceSettings' | 'siteSettings'\n\n/** One icon per idea: the same row draws the same picture in both scopes. */\nexport interface NativeNavIcon {\n /** An SF Symbol name. */\n apple: string\n /** A Material Symbol name, as `AglynIcons.named` takes it. */\n android: string\n}\n\n/**\n * Where a row's console twin lives:\n * - `orgTab` / `hostTab`: a console tab, by its id (`org-nav-tabs.ts`,\n * `host-nav-tabs.ts`);\n * - `orgPluginTab` / `hostPluginTab`: a plugin's `orgNavItems` / `navItems`\n * entry, by its href;\n * - `orgPluginSection` / `hostPluginSection`: a section of a plugin's hub, as\n * `{href}/{sectionId}`;\n * - `setupSection`: a site's Setup section, by its id (`setup-sections.ts`);\n * - `hostAdminSection`, `orgSettingsSection`, `teamSection`,\n * `billingSection`: a section of those hubs, by its `Route` name;\n * - `consoleWidget`: a plugin's card, as `{slot}/{widgetId}`;\n * - `shell`: a place the app's shell owns (Home, Overview's page, the\n * settings modes), whose console twin is the page named in `id`;\n * - `nativeOnly`: a native screen the console has no page for.\n */\nexport type NativeNavConsoleSurface =\n | 'orgTab'\n | 'hostTab'\n | 'orgPluginTab'\n | 'hostPluginTab'\n | 'orgPluginSection'\n | 'hostPluginSection'\n | 'setupSection'\n | 'hostAdminSection'\n | 'orgSettingsSection'\n | 'teamSection'\n | 'billingSection'\n | 'consoleWidget'\n | 'shell'\n | 'nativeOnly'\n\nexport interface NativeNavConsoleRef {\n surface: NativeNavConsoleSurface\n id: string\n}\n\n/** A section inside a row's area, as the console's section rail lists it. */\nexport interface NativeNavSection {\n id: string\n label: string\n screen: string\n params?: Record<string, string>\n /** Set only when the section belongs to another plugin than its row's. */\n pluginId?: string\n /** The help docs page for it; its row's, unless the console names its own. */\n docs?: string\n console: NativeNavConsoleRef\n}\n\n/** An action the area offers from its title bar (Scan stock, New product). */\nexport interface NativeNavAction {\n id: string\n label: string\n icon: NativeNavIcon\n screen: string\n params?: Record<string, string>\n}\n\nexport interface NativeNavRow {\n /** The idea's id: the same in every list that shows it (`media`). */\n id: string\n /** The console's word. */\n label: string\n /**\n * The console's word when the native label is a decision of its own\n * (Overview for the site's analytics, Zach 2026-10-18).\n */\n consoleLabel?: string\n icon: NativeNavIcon\n /** The native screen the row opens. */\n screen: string\n params?: Record<string, string>\n /** The plugin the row belongs to: off for the workspace or site, the row hides. */\n pluginId?: string\n /** Only a site admin sees the row, as only they see the console's Admin tab. */\n requiresHostAdmin?: boolean\n /** A settings row's one line, in the words the screens already use. */\n description?: string\n /** Search words besides the label, so typing \"billing\" finds Plan. */\n keywords?: string[]\n /** Where the row sits in its group, ascending; a plugin's row is placed by it. */\n order?: number\n /**\n * The help docs page for the place, as the console's own help names it\n * (its `docsTopic` and `docsAnchor`, or the page's `help` prop): a docs-site\n * path with its anchor, e.g. `/content-and-data/crm/overview#at-the-organization-level`.\n * The apps open it in the in-app browser, on the docs origin.\n */\n docs?: string\n sections?: NativeNavSection[]\n actions?: NativeNavAction[]\n console: NativeNavConsoleRef\n}\n\nexport interface NativeNavGroup {\n id: string\n /** The heading; absent for a group drawn without one. */\n label?: string\n /** Folded at rest unless it holds the screen in use, remembered per device. */\n foldable: boolean\n /** `starred`: the person's starred items for this scope, drawn by the shell. */\n dynamic?: 'starred'\n rows: NativeNavRow[]\n}\n\nexport interface NativeNavList {\n id: NativeNavListId\n /** The settings mode's title, after its owner's name (\"Juniper Street Co. settings\"). */\n title?: string\n groups: NativeNavGroup[]\n}\n\n/** A console place no row holds, and where the apps put it instead. */\nexport interface NativeNavElsewhere {\n console: NativeNavConsoleRef\n where: string\n}\n\n/** A plugin's row, and the list and group it goes in. */\nexport interface NativeNavContribution {\n list: NativeNavListId\n /** A group of that list, by id. */\n group: string\n row: NativeNavRow\n}\n\n/** Where the Create new menu is offered: the whole workspace, or one site. */\nexport type NativeNavCreateScope = 'workspace' | 'site'\n\n/**\n * One item of the Create new menu (\"+\" on the rail, the center tab on\n * phones): what the console offers to create from that scope, opening the\n * area's own create form.\n */\nexport interface NativeNavCreateItem {\n id: string\n /** The thing made, in the console's words (\"Draft order\", \"Service\"). */\n label: string\n icon: NativeNavIcon\n /** The native screen the item opens, with `params` that open its create form. */\n screen: string\n params?: Record<string, string>\n /** The plugin it belongs to: off for the workspace or site, the item is not offered. */\n pluginId?: string\n /** Only a site admin is offered it. */\n requiresHostAdmin?: boolean\n /** The workspace permission the console's create action asks for (`hosts.create`, `data.manage`). */\n permission?: string\n /** The site roles that may make it, as the rules hold them (`canWriteHostContent`). */\n hostRoles?: string[]\n /** The plan feature it needs; without it the item is shown blocked, with `blockedReason`. */\n planFeature?: string\n /** Why it is blocked when the plan lacks `planFeature`; the default reason otherwise. */\n blockedReason?: string\n /** Where it sits in the menu, ascending. */\n order?: number\n /** Where the console offers the same create action. */\n console: NativeNavConsoleRef\n}\n\n/** One scope's Create new menu. */\nexport interface NativeNavCreateList {\n scope: NativeNavCreateScope\n items: NativeNavCreateItem[]\n}\n\n/** A plugin's Create new item, and the scope that offers it. */\nexport interface NativeNavCreateContribution {\n scope: NativeNavCreateScope\n item: NativeNavCreateItem\n}\n\nexport interface NativeNavManifest {\n lists: NativeNavList[]\n /** The Create new menu per scope (AGL-3943). */\n create?: NativeNavCreateList[]\n /** Destinations the shells own, which no plugin registers. */\n shellScreens: string[]\n elsewhere: NativeNavElsewhere[]\n}\n\n/** The shells' own destinations. */\nexport const NATIVE_NAV_SHELL_SCREENS: readonly string[] = [\n 'shell.home',\n 'shell.analytics',\n 'shell.workspaceSettings',\n 'shell.siteSettings',\n]\n\n/** An icon pair, for the rows here and in the plugins. */\nexport const nativeNavIcon = (apple: string, android: string): NativeNavIcon => ({ apple, android })\n\n/** A console reference, for the rows here and in the plugins. */\nexport const nativeNavRef = (surface: NativeNavConsoleSurface, id: string): NativeNavConsoleRef => ({\n surface,\n id,\n})\n\n/** A section of a plugin hub, at the scope its row stands in. */\nexport function nativeNavHubSection(\n scope: 'org' | 'host',\n href: string,\n id: string,\n label: string,\n screen: string,\n extra: Partial<Pick<NativeNavSection, 'params' | 'pluginId'>> = {},\n): NativeNavSection {\n return {\n id,\n label,\n screen,\n ...extra,\n console: nativeNavRef(scope === 'org' ? 'orgPluginSection' : 'hostPluginSection', `${href}/${id}`),\n }\n}\n\nconst icon = nativeNavIcon\nconst ref = nativeNavRef\n\nconst ICONS = {\n home: icon('house', 'home'),\n overview: icon('chart.bar', 'bar_chart'),\n sites: icon('globe', 'public'),\n pages: icon('doc.text', 'description'),\n media: icon('photo.on.rectangle', 'photo_library'),\n settings: icon('gearshape', 'settings'),\n emails: icon('envelope', 'mail'),\n members: icon('person.2', 'group'),\n roles: icon('person.badge.key', 'admin_panel_settings'),\n activity: icon('clock.arrow.circlepath', 'history'),\n plan: icon('creditcard', 'credit_card'),\n usage: icon('gauge.with.dots.needle.33percent', 'data_usage'),\n invoices: icon('doc.plaintext', 'receipt_long'),\n billingSettings: icon('slider.horizontal.3', 'tune'),\n plugins: icon('puzzlepiece.extension', 'extension'),\n branding: icon('paintbrush', 'brush'),\n sso: icon('key.viewfinder', 'vpn_key'),\n profile: icon('building.2', 'apartment'),\n apiKeys: icon('key', 'key'),\n integrations: icon('point.3.connected.trianglepath.dotted', 'hub'),\n privacy: icon('hand.raised', 'privacy_tip'),\n holds: icon('exclamationmark.triangle', 'warning'),\n importExport: icon('arrow.up.arrow.down', 'sync'),\n ownership: icon('person.crop.circle.badge.checkmark', 'manage_accounts'),\n delete: icon('trash', 'delete_forever'),\n details: icon('info.circle', 'info'),\n business: icon('briefcase', 'business'),\n seo: icon('magnifyingglass', 'travel_explore'),\n tracking: icon('chart.line.uptrend.xyaxis', 'query_stats'),\n theme: icon('paintpalette', 'palette'),\n domain: icon('link', 'domain'),\n security: icon('lock', 'security'),\n errorPages: icon('exclamationmark.circle', 'error_outline'),\n backup: icon('square.and.arrow.down', 'backup'),\n} as const\n\nconst HOME_ROW: NativeNavRow = {\n id: 'home',\n label: 'Home',\n icon: ICONS.home,\n screen: 'shell.home',\n order: 10,\n console: ref('shell', 'home'),\n}\n\nconst WORKSPACE: NativeNavList = {\n id: 'workspace',\n groups: [\n { id: 'top', foldable: false, rows: [HOME_ROW] },\n { id: 'starred', label: 'Starred', foldable: true, dynamic: 'starred', rows: [] },\n {\n id: 'workspace',\n foldable: false,\n rows: [\n {\n id: 'sites',\n label: 'Sites',\n icon: ICONS.sites,\n screen: 'site.sites',\n order: 10,\n docs: '/getting-started/console-tour#the-sites-list',\n console: ref('orgTab', 'nav-tab-org-sites'),\n },\n {\n id: 'media',\n label: 'Media',\n icon: ICONS.media,\n screen: 'site.media',\n order: 90,\n console: ref('orgTab', 'nav-tab-org-media'),\n },\n ],\n },\n ],\n}\n\nconst SITE: NativeNavList = {\n id: 'site',\n groups: [\n {\n id: 'top',\n foldable: false,\n rows: [\n HOME_ROW,\n {\n id: 'overview',\n label: 'Overview',\n consoleLabel: 'Analytics',\n icon: ICONS.overview,\n screen: 'shell.analytics',\n order: 20,\n keywords: ['analytics', 'traffic', 'visitors'],\n console: ref('hostTab', 'nav-tab-analytics'),\n },\n ],\n },\n { id: 'starred', label: 'Starred', foldable: true, dynamic: 'starred', rows: [] },\n {\n id: 'website',\n label: 'Website',\n foldable: true,\n rows: [\n {\n id: 'pages',\n label: 'Pages',\n icon: ICONS.pages,\n screen: 'site.pages',\n order: 10,\n sections: [\n { id: 'pages', label: 'Pages', screen: 'site.pages', console: ref('hostTab', 'nav-tab-screens') },\n { id: 'components', label: 'Components', screen: 'site.components', console: ref('hostTab', 'nav-tab-components') },\n { id: 'layouts', label: 'Layouts', screen: 'site.layouts', console: ref('hostTab', 'nav-tab-layouts') },\n { id: 'templates', label: 'Templates', screen: 'site.templates', console: ref('hostTab', 'nav-tab-templates') },\n { id: 'content', label: 'Content', screen: 'site.content', console: ref('hostTab', 'nav-tab-content') },\n ],\n console: ref('hostTab', 'nav-tab-screens'),\n },\n {\n id: 'media',\n label: 'Media',\n icon: ICONS.media,\n screen: 'site.media',\n order: 20,\n console: ref('hostTab', 'nav-tab-media'),\n },\n ],\n },\n { id: 'sell', label: 'Sell', foldable: true, rows: [] },\n { id: 'customers', label: 'Customers', foldable: true, rows: [] },\n { id: 'more', label: 'More', foldable: true, rows: [] },\n {\n id: 'settings',\n foldable: false,\n rows: [\n {\n id: 'siteSettings',\n label: 'Site settings',\n icon: ICONS.settings,\n screen: 'shell.siteSettings',\n order: 10,\n console: ref('shell', 'siteSettings'),\n },\n ],\n },\n ],\n}\n\n/** Each row's place, in the order written. */\nconst ordered = (rows: NativeNavRow[]): NativeNavRow[] =>\n rows.map((row, index) => ({ ...row, order: row.order ?? (index + 1) * 10 }))\n\n/** The help page each settings hub's `help` prop names, the rows' docs. */\nconst HUB_DOCS: Partial<Record<NativeNavConsoleSurface, string>> = {\n teamSection: '/workspace-and-billing/teams-and-roles/overview#team-page',\n billingSection: '/workspace-and-billing/billing-and-plans/overview#billing-page',\n orgSettingsSection: '/getting-started/console-tour#organization-settings',\n hostAdminSection: '/getting-started/create-a-site#site-admin',\n}\n\nconst setupRow = (\n id: string,\n label: string,\n rowIcon: NativeNavIcon,\n description: string,\n keywords?: string[],\n): NativeNavRow => ({\n id,\n label,\n icon: rowIcon,\n screen: id === 'theme' ? 'site.theme' : 'site.setup',\n ...(id === 'theme' ? {} : { params: { section: id } }),\n description,\n ...(keywords ? { keywords } : {}),\n console: ref('setupSection', id),\n})\n\nconst adminRow = (\n id: string,\n label: string,\n rowIcon: NativeNavIcon,\n screen: string,\n route: string,\n): NativeNavRow => ({\n id,\n label,\n icon: rowIcon,\n screen,\n requiresHostAdmin: true,\n docs: HUB_DOCS.hostAdminSection,\n console: ref('hostAdminSection', route),\n})\n\nconst settingsRow = (\n surface: NativeNavConsoleSurface,\n id: string,\n label: string,\n rowIcon: NativeNavIcon,\n screen: string,\n route: string,\n extra: Partial<Pick<NativeNavRow, 'keywords' | 'order'>> = {},\n): NativeNavRow => ({\n id,\n label,\n icon: rowIcon,\n screen,\n ...extra,\n ...(HUB_DOCS[surface] ? { docs: HUB_DOCS[surface] } : {}),\n console: ref(surface, route),\n})\n\nconst WORKSPACE_SETTINGS: NativeNavList = {\n id: 'workspaceSettings',\n title: 'settings',\n groups: [\n {\n id: 'team',\n label: 'Team',\n foldable: false,\n rows: ordered([\n settingsRow('teamSection', 'members', 'Members', ICONS.members, 'core.team', 'MANAGE_TEAM_MEMBERS', { keywords: ['team', 'invite', 'people'] }),\n settingsRow('teamSection', 'roles', 'Custom roles', ICONS.roles, 'core.team.roles', 'MANAGE_TEAM_ROLES', { keywords: ['permissions'] }),\n settingsRow('teamSection', 'activity', 'Recent activity', ICONS.activity, 'core.team.activity', 'MANAGE_TEAM_ACTIVITY', { keywords: ['audit log'] }),\n ]),\n },\n {\n id: 'billing',\n label: 'Billing',\n foldable: false,\n rows: [\n settingsRow('billingSection', 'plan', 'Plan', ICONS.plan, 'core.billing', 'MANAGE_BILLING', { order: 10, keywords: ['billing', 'upgrade', 'subscription'] }),\n settingsRow('billingSection', 'usage', 'Usage', ICONS.usage, 'core.billing.usage', 'MANAGE_BILLING_USAGE', { order: 20, keywords: ['billing', 'limits'] }),\n settingsRow('billingSection', 'invoices', 'Invoices', ICONS.invoices, 'core.billing.invoices', 'MANAGE_BILLING_INVOICES', { order: 40, keywords: ['billing', 'receipts'] }),\n settingsRow('billingSection', 'billingSettings', 'Settings', ICONS.billingSettings, 'core.billing.settings', 'MANAGE_BILLING_SETTINGS', { order: 50, keywords: ['billing', 'payment method', 'tax'] }),\n ],\n },\n {\n id: 'workspace',\n label: 'Workspace',\n foldable: false,\n rows: ordered([\n settingsRow('orgTab', 'plugins', 'Plugins', ICONS.plugins, 'core.plugins', 'nav-tab-org-plugins'),\n settingsRow('orgSettingsSection', 'branding', 'Branding', ICONS.branding, 'core.settings.branding', 'ORG_SETTINGS_BRANDING', { keywords: ['white label', 'logo', 'colors'] }),\n settingsRow('orgSettingsSection', 'sso', 'Single sign-on', ICONS.sso, 'core.settings.sso', 'ORG_SETTINGS_SSO', { keywords: ['sso', 'saml'] }),\n settingsRow('orgSettingsSection', 'profile', 'Profile', ICONS.profile, 'core.settings.profile', 'ORG_SETTINGS_PROFILE'),\n settingsRow('orgSettingsSection', 'apiKeys', 'API keys', ICONS.apiKeys, 'core.settings.apiKeys', 'ORG_SETTINGS_API_KEYS'),\n settingsRow('orgSettingsSection', 'integrations', 'Integrations', ICONS.integrations, 'core.settings.integrations', 'ORG_SETTINGS_INTEGRATIONS'),\n settingsRow('orgSettingsSection', 'general', 'General', ICONS.settings, 'core.settings.general', 'ORG_SETTINGS_GENERAL', { keywords: ['name', 'address'] }),\n ]),\n },\n {\n id: 'data',\n label: 'Data & compliance',\n foldable: false,\n rows: ordered([\n settingsRow('orgSettingsSection', 'privacy', 'Privacy', ICONS.privacy, 'core.settings.privacy', 'ORG_SETTINGS_PRIVACY', { keywords: ['gdpr', 'erase'] }),\n settingsRow('orgSettingsSection', 'holds', 'Holds & reviews', ICONS.holds, 'core.settings.holds', 'ORG_SETTINGS_HOLDS'),\n settingsRow('orgSettingsSection', 'importExport', 'Import & export', ICONS.importExport, 'core.settings.data', 'ORG_SETTINGS_DATA', { keywords: ['csv', 'export'] }),\n ]),\n },\n {\n id: 'danger',\n label: 'Danger zone',\n foldable: false,\n rows: ordered([\n settingsRow('orgSettingsSection', 'ownership', 'Ownership', ICONS.ownership, 'core.settings.ownership', 'ORG_SETTINGS_OWNERSHIP', { keywords: ['transfer'] }),\n settingsRow('orgSettingsSection', 'delete', 'Delete', ICONS.delete, 'core.settings.delete', 'ORG_SETTINGS_DELETE'),\n ]),\n },\n ],\n}\n\nconst SITE_SETTINGS: NativeNavList = {\n id: 'siteSettings',\n title: 'settings',\n groups: [\n {\n id: 'people',\n foldable: false,\n rows: ordered([\n {\n id: 'users',\n label: 'Users',\n icon: ICONS.members,\n screen: 'core.site.users',\n keywords: ['team', 'collaborators'],\n console: ref('hostTab', 'nav-tab-users'),\n },\n ]),\n },\n {\n id: 'setup',\n label: 'Setup',\n foldable: false,\n rows: ordered([\n setupRow('details', 'Basic details', ICONS.details, 'Logo, business details, layout and languages'),\n setupRow('business', 'Business profile', ICONS.business, 'What the business is, for everything that writes about it'),\n setupRow('seo', 'SEO', ICONS.seo, 'Search title, social image, business profile and verification', ['search']),\n setupRow('tracking', 'Tracking', ICONS.tracking, 'Analytics, ad tags and the consent banner', ['cookies', 'pixels']),\n setupRow('theme', 'Theme', ICONS.theme, 'Colors, font, shape and your saved themes', ['colors', 'fonts']),\n setupRow('emails', 'Emails', ICONS.emails, 'The emails your site sends to customers'),\n setupRow('integrations', 'Integrations', ICONS.integrations, 'Email platforms, Zapier, live chat and the other tools your site connects to'),\n ]),\n },\n {\n id: 'admin',\n label: 'Admin',\n foldable: false,\n rows: ordered([\n adminRow('general', 'General', ICONS.settings, 'core.site.general', 'HOST_ADMIN_GENERAL'),\n adminRow('plugins', 'Plugins', ICONS.plugins, 'core.site.plugins', 'HOST_ADMIN_PLUGINS'),\n adminRow('domain', 'Custom Domain', ICONS.domain, 'core.site.domain', 'HOST_ADMIN_DOMAIN'),\n adminRow('security', 'Security', ICONS.security, 'core.site.security', 'HOST_ADMIN_SECURITY'),\n adminRow('errorPages', 'Error pages', ICONS.errorPages, 'core.site.errorPages', 'HOST_ADMIN_ERROR_PAGES'),\n adminRow('activity', 'Activity', ICONS.activity, 'core.site.activity', 'HOST_ADMIN_ACTIVITY'),\n adminRow('backup', 'Backup & template', ICONS.backup, 'core.site.backup', 'HOST_ADMIN_BACKUP'),\n adminRow('danger', 'Danger zone', ICONS.delete, 'core.site.delete', 'HOST_ADMIN_DANGER'),\n ]),\n },\n ],\n}\n\nconst CREATE: NativeNavCreateList[] = [\n {\n scope: 'workspace',\n items: [\n {\n id: 'site',\n label: 'Site',\n icon: ICONS.sites,\n screen: 'site.sites',\n params: { new: '1' },\n permission: 'hosts.create',\n order: 10,\n console: ref('orgTab', 'nav-tab-org-sites'),\n },\n ],\n },\n {\n scope: 'site',\n items: [\n {\n id: 'page',\n label: 'Page',\n icon: ICONS.pages,\n screen: 'site.pages',\n params: { new: '1' },\n hostRoles: ['admin', 'editor', 'author'],\n order: 10,\n console: ref('hostTab', 'nav-tab-screens'),\n },\n ],\n },\n]\n\n/**\n * The core's half of the manifest: every list and group, and the core's own\n * rows. The manifest the apps read (`ContractValues.nativeNavManifest`) is\n * this with each plugin's `NATIVE_NAV_ROWS` placed by `assembleNativeNav`.\n */\nexport const NATIVE_NAV_MANIFEST: NativeNavManifest = {\n lists: [WORKSPACE, SITE, WORKSPACE_SETTINGS, SITE_SETTINGS],\n create: CREATE,\n shellScreens: [...NATIVE_NAV_SHELL_SCREENS],\n elsewhere: [\n { console: ref('hostTab', 'nav-tab-dashboard'), where: 'Home, inside the site (shell.home)' },\n { console: ref('hostTab', 'nav-tab-setup'), where: 'Site settings → Setup' },\n { console: ref('hostTab', 'nav-tab-admin'), where: 'Site settings → Admin' },\n { console: ref('orgTab', 'nav-tab-org-team'), where: 'Workspace settings → Team' },\n { console: ref('orgTab', 'nav-tab-org-billing'), where: 'Workspace settings → Billing' },\n { console: ref('orgTab', 'nav-tab-org-settings'), where: 'Workspace settings' },\n { console: ref('orgTab', 'nav-tab-org-support'), where: 'Help menu → Contact support (core.support)' },\n ],\n}\n\n/**\n * The manifest with the plugins' rows placed: each into its list's group by\n * `order` (a tie keeps the core's row first, then registration order). A row\n * naming a list or group the core does not have is refused by name, so a\n * plugin cannot quietly invent a group.\n */\nexport function assembleNativeNav(\n core: NativeNavManifest,\n contributions: readonly NativeNavContribution[],\n elsewhere: readonly NativeNavElsewhere[] = [],\n creates: readonly NativeNavCreateContribution[] = [],\n): NativeNavManifest {\n const byOrder = <T extends { order?: number }>(entries: T[]): T[] =>\n entries\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) => (a.entry.order ?? 0) - (b.entry.order ?? 0) || a.index - b.index)\n .map(({ entry }) => entry)\n const lists = core.lists.map((list) => ({\n ...list,\n groups: list.groups.map((group) => ({ ...group, rows: [...group.rows] })),\n }))\n for (const { list: listId, group: groupId, row } of contributions) {\n const group = lists.find((list) => list.id === listId)?.groups.find((entry) => entry.id === groupId)\n if (!group || group.dynamic) {\n throw new Error(`native nav: ${row.id} names ${listId}/${groupId}, which is not a group of rows`)\n }\n if (group.rows.some((entry) => entry.id === row.id)) {\n throw new Error(`native nav: ${listId}/${groupId} holds ${row.id} twice`)\n }\n group.rows.push(row)\n }\n for (const list of lists) {\n for (const group of list.groups) {\n // A section is helped by its row's page unless the console names its own.\n group.rows = byOrder(group.rows).map((row) =>\n row.docs && row.sections\n ? { ...row, sections: row.sections.map((section) => (section.docs ? section : { ...section, docs: row.docs })) }\n : row,\n )\n }\n }\n const create = (core.create ?? []).map((entry) => ({ ...entry, items: [...entry.items] }))\n for (const { scope, item } of creates) {\n const target = create.find((entry) => entry.scope === scope)\n if (!target) throw new Error(`native nav: create item ${item.id} names ${scope}, which has no menu`)\n if (target.items.some((entry) => entry.id === item.id)) {\n throw new Error(`native nav: the ${scope} create menu holds ${item.id} twice`)\n }\n target.items.push(item)\n }\n return {\n ...core,\n lists,\n create: create.map((entry) => ({ ...entry, items: byOrder(entry.items) })),\n elsewhere: [...core.elsewhere, ...elsewhere],\n }\n}\n\n/** What a Create new item that cannot be used says, when its own reason does not apply. */\nexport const NATIVE_CREATE_PERMISSION_REASON =\n \"Your role can't create this here. Ask an owner or admin of the workspace.\"\nexport const NATIVE_CREATE_SITE_ROLE_REASON = \"Your role on this site can't create this. Ask a site admin.\"\nexport const NATIVE_CREATE_PLAN_REASON = \"Your plan doesn't include this. See the plans in Billing.\"\n\n/** A Create new item as one scope offers it. */\nexport interface ResolvedCreateItem extends NativeNavCreateItem {\n /** Shown, but disabled with `reason`: a prerequisite stands between the person and it. */\n blocked: boolean\n reason?: string\n}\n\n/**\n * The Create new menu for the workspace or site in hand. An item of a plugin\n * that is off is not offered, nor an admin-only item to a non-admin. One the\n * person may not use is SHOWN, disabled with its reason (prerequisites are\n * shown, never hidden): a permission or site role they lack, then a plan\n * feature the workspace lacks. `permissions` and `features` are the\n * workspace's resolved answers (an absent key is not held); `hostRole` is\n * the person's role on the site, null at the workspace.\n */\nexport function resolveCreateList(\n manifest: NativeNavManifest,\n scope: NativeNavCreateScope,\n enabledPluginIds: readonly string[],\n permissions: Readonly<Record<string, boolean>>,\n features: Readonly<Record<string, boolean>>,\n hostRole: string | null,\n): ResolvedCreateItem[] {\n const on = new Set(enabledPluginIds)\n const items = manifest.create?.find((entry) => entry.scope === scope)?.items ?? []\n return items\n .filter((item) => (!item.pluginId || on.has(item.pluginId)) && (!item.requiresHostAdmin || hostRole === 'admin'))\n .map((item): ResolvedCreateItem => {\n if (item.permission && permissions[item.permission] !== true) {\n return { ...item, blocked: true, reason: NATIVE_CREATE_PERMISSION_REASON }\n }\n if (item.hostRoles && !item.hostRoles.includes(hostRole ?? '')) {\n return { ...item, blocked: true, reason: NATIVE_CREATE_SITE_ROLE_REASON }\n }\n if (item.planFeature && features[item.planFeature] !== true) {\n return { ...item, blocked: true, reason: item.blockedReason ?? NATIVE_CREATE_PLAN_REASON }\n }\n return { ...item, blocked: false }\n })\n}\n\n/** A list as one scope shows it: rows for plugins that are off, or admin rows for a non-admin, left out. */\nexport interface ResolvedNavList {\n id: NativeNavListId\n title?: string\n groups: NativeNavGroup[]\n}\n\n/**\n * One list for the workspace or site in hand, from the assembled manifest\n * (`ContractValues.nativeNavManifest`). `enabledPluginIds` is the site's\n * effective set (`resolveHostEnabledPlugins`) in site scope and the\n * workspace's (`resolveEnabledPlugins`) otherwise. A section of another\n * plugin than its row's hides with that plugin. A group left with no rows is\n * dropped, except the starred group, which the shell fills.\n */\nexport function resolveNavList(\n manifest: NativeNavManifest,\n listId: NativeNavListId,\n enabledPluginIds: readonly string[],\n hostAdmin: boolean,\n): ResolvedNavList {\n const list = manifest.lists.find((entry) => entry.id === listId)\n if (!list) return { id: listId, groups: [] }\n const on = new Set(enabledPluginIds)\n const shows = (pluginId?: string) => !pluginId || on.has(pluginId)\n const groups: NativeNavGroup[] = []\n for (const group of list.groups) {\n const rows = group.rows\n .filter((row) => shows(row.pluginId) && (hostAdmin || !row.requiresHostAdmin))\n .map((row) =>\n row.sections\n ? { ...row, sections: row.sections.filter((section) => shows(section.pluginId)) }\n : row,\n )\n if (!rows.length && !group.dynamic) continue\n groups.push({ ...group, rows })\n }\n return { id: list.id, ...(list.title ? { title: list.title } : {}), groups }\n}\n"],"names":["NATIVE_NAV_SHELL_SCREENS","nativeNavIcon","apple","android","nativeNavRef","surface","id","nativeNavHubSection","scope","href","label","screen","extra","console","icon","ref","ICONS","home","overview","sites","pages","media","settings","emails","members","roles","activity","plan","usage","invoices","billingSettings","plugins","branding","sso","profile","apiKeys","integrations","privacy","holds","importExport","ownership","delete","details","business","seo","tracking","theme","domain","security","errorPages","backup","HOME_ROW","order","WORKSPACE","groups","foldable","rows","dynamic","docs","SITE","consoleLabel","keywords","sections","ordered","map","row","index","HUB_DOCS","teamSection","billingSection","orgSettingsSection","hostAdminSection","setupRow","rowIcon","description","params","section","adminRow","route","requiresHostAdmin","settingsRow","WORKSPACE_SETTINGS","title","SITE_SETTINGS","CREATE","items","new","permission","hostRoles","NATIVE_NAV_MANIFEST","lists","create","shellScreens","elsewhere","where","assembleNativeNav","core","contributions","creates","byOrder","entries","entry","sort","a","b","list","group","listId","groupId","find","Error","some","push","item","target","NATIVE_CREATE_PERMISSION_REASON","NATIVE_CREATE_SITE_ROLE_REASON","NATIVE_CREATE_PLAN_REASON","resolveCreateList","manifest","enabledPluginIds","permissions","features","hostRole","on","Set","filter","pluginId","has","blocked","reason","includes","planFeature","blockedReason","resolveNavList","hostAdmin","shows","length"],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * THE NATIVE APPS' THEMES, AS DATA (AGL-3950).
19
+ *
20
+ * The values are read from the Native App Figma file's variables (Themes,
21
+ * page 2:8; collections Aglyn / Theme, Aglyn / Appearance, Aglyn / Accent,
22
+ * Aglyn / Brand and Aglyn / Density), which win wherever they define a value:
23
+ *
24
+ * - `THEME_PALETTES`: Aglyn is the look that ships, the console's resolved
25
+ * MUI scheme (see `AGLYN_LIGHT`); Quiet, Night and High contrast, light and
26
+ * dark, are exactly as Figma's Theme modes hold them. Ocean and Warm exist in Figma
27
+ * only as four-color previews (rail, surface, canvas, accent), so their
28
+ * full palettes are derived here by `deriveThemeFromPreview`, the rule
29
+ * below, and drawn back into Figma as swatch boards.
30
+ * - `THEME_ACCENTS`: the Accent modes Blue, Violet, Pink and Workspace
31
+ * brand, exactly. `deriveAccent` returns them for their ring colors and
32
+ * derives any other color (a picked accent, a workspace's brand) by rule.
33
+ * - `THEME_ACCENT_SWATCHES`: the six swatches the Theme settings sheet shows.
34
+ * - `THEME_DENSITIES`: Comfortable and Compact.
35
+ *
36
+ * Contrast is WCAG 2's relative luminance, as `accessible-shade.ts` (the
37
+ * console's theme) measures it; lightness steps are HSL lightness, as it
38
+ * walks them.
39
+ *
40
+ * NO IMPORTS, on purpose: the native apps read the values, the types and the
41
+ * answers of these functions through the generated contracts.
42
+ */
43
+ /** A theme the apps offer. */
44
+ export type ThemePaletteId = 'aglyn' | 'quiet' | 'night' | 'ocean' | 'warm' | 'highContrast';
45
+ /** One appearance of a theme: every color a native screen draws from. */
46
+ export interface ThemeColors {
47
+ canvas: string;
48
+ surface: string;
49
+ raised: string;
50
+ sunken: string;
51
+ rail: string;
52
+ hover: string;
53
+ titlebar: string;
54
+ borderSubtle: string;
55
+ borderStrong: string;
56
+ textPrimary: string;
57
+ textSecondary: string;
58
+ textTertiary: string;
59
+ successBg: string;
60
+ successFg: string;
61
+ warningBg: string;
62
+ warningFg: string;
63
+ dangerBg: string;
64
+ dangerFg: string;
65
+ infoBg: string;
66
+ infoFg: string;
67
+ newBg: string;
68
+ newFg: string;
69
+ /** `#RRGGBBAA`: the wash behind a sheet. */
70
+ scrim: string;
71
+ /** A destructive button's fill, and its hover and pressed fills. */
72
+ dangerFill: string;
73
+ dangerFillHover: string;
74
+ dangerFillPressed: string;
75
+ }
76
+ /**
77
+ * Where a theme's values come from: the console's resolved MUI scheme (the
78
+ * look that ships, Aglyn), Figma's variables, or derived from a Figma preview.
79
+ */
80
+ export type ThemeSource = 'console' | 'figma' | 'derived';
81
+ export interface ThemePalette {
82
+ id: ThemePaletteId;
83
+ /** The name a picker shows; empty when `brandLabel` says to show the configured brand name. */
84
+ label: string;
85
+ /** The theme is named after the product: show the build's configured brand name (white-label safe). */
86
+ brandLabel?: boolean;
87
+ light: ThemeColors;
88
+ dark: ThemeColors;
89
+ /** The theme's own accent ("Accent: Theme"), as a raw color for `deriveAccent`. */
90
+ accent: string;
91
+ /** Night is the same in both appearances: the theme is always dark. */
92
+ alwaysDark?: boolean;
93
+ source: ThemeSource;
94
+ }
95
+ /** An accent, as every control that paints it reads it. */
96
+ export interface ThemeAccent {
97
+ /** A filled control's background. */
98
+ fill: string;
99
+ /** An icon or an indicator in the accent, on the light surfaces. */
100
+ icon: string;
101
+ /** `#RRGGBBAA`: a selected row's or a chip's wash. */
102
+ soft: string;
103
+ /** The focus ring: the raw accent. */
104
+ ring: string;
105
+ /** Text and icons ON `fill`. */
106
+ on: string;
107
+ hover: string;
108
+ pressed: string;
109
+ /** The accent as text on the light surface, at 4.5:1. */
110
+ textLight: string;
111
+ /** The accent as text on the dark surface, at 4.5:1. */
112
+ textDark: string;
113
+ }
114
+ /** An accent the Theme settings sheet offers by name (Figma's Accent modes). */
115
+ export interface ThemeNamedAccent {
116
+ id: string;
117
+ label: string;
118
+ accent: ThemeAccent;
119
+ }
120
+ /** A swatch of the accent picker. */
121
+ export interface ThemeAccentSwatch {
122
+ id: string;
123
+ label: string;
124
+ color: string;
125
+ }
126
+ export type ThemeDensityId = 'comfortable' | 'compact';
127
+ /** One density's sizes, in points (Apple) and dp (Android). */
128
+ export interface ThemeDensity {
129
+ id: ThemeDensityId;
130
+ label: string;
131
+ space2: number;
132
+ space4: number;
133
+ space6: number;
134
+ space8: number;
135
+ space10: number;
136
+ space12: number;
137
+ space16: number;
138
+ space20: number;
139
+ space24: number;
140
+ space32: number;
141
+ space40: number;
142
+ space48: number;
143
+ space64: number;
144
+ radiusXs: number;
145
+ radiusSm: number;
146
+ radiusMd: number;
147
+ radiusLg: number;
148
+ radiusXl: number;
149
+ radius2xl: number;
150
+ radiusFull: number;
151
+ rowHeight: number;
152
+ controlHeight: number;
153
+ listRowHeight: number;
154
+ phoneRowHeight: number;
155
+ titlebarHeight: number;
156
+ }
157
+ /** The four colors Figma previews a theme by. */
158
+ export interface ThemePreview {
159
+ rail: string;
160
+ surface: string;
161
+ canvas: string;
162
+ accent: string;
163
+ }
164
+ /** Whether a value is `#RRGGBB`. */
165
+ export declare function isThemeColor(value: unknown): value is string;
166
+ /** WCAG 2 contrast between two `#RRGGBB` colors, as the console's `contrastRatio` measures it. */
167
+ export declare function themeContrast(a: string, b: string): number;
168
+ /** `from` moved `amount` (0–1) of the way to `to`, per sRGB channel. */
169
+ export declare function themeLerp(from: string, to: string, amount: number): string;
170
+ /** Text that must read on every surface: WCAG AA. */
171
+ export declare const THEME_TEXT_CONTRAST = 4.5;
172
+ /** An icon, a border or an indicator: WCAG AA for non-text. */
173
+ export declare const THEME_NON_TEXT_CONTRAST = 3;
174
+ /** A light and a dark palette. */
175
+ export interface ThemeColorsPair {
176
+ light: ThemeColors;
177
+ dark: ThemeColors;
178
+ }
179
+ /**
180
+ * The palettes `deriveThemeFromPreview` starts from (the original Figma Aglyn
181
+ * mode), exported so each platform can port the derivation and replay its
182
+ * cases against the same base.
183
+ */
184
+ export declare const THEME_FIGMA_BASE: ThemeColorsPair;
185
+ /** The Aglyn theme's fields the console's scheme supplies; the rest are Figma's Aglyn mode. */
186
+ export declare const THEME_CONSOLE_FIELDS: readonly string[];
187
+ /** Figma's previews of the two themes it does not hold in full. */
188
+ export declare const THEME_PREVIEWS: Readonly<Record<'ocean' | 'warm', ThemePreview>>;
189
+ /**
190
+ * The rail color a theme's DARK appearance is tinted toward. Ocean's rail is
191
+ * already dark, so it is its own seed; Warm's is a light sand, so its dark
192
+ * appearance leans to a dark sand instead.
193
+ */
194
+ export declare const THEME_DARK_RAIL_SEEDS: Readonly<Record<'ocean' | 'warm', string>>;
195
+ /**
196
+ * A theme's full palette from Figma's four-color preview (AGL-3950), by the
197
+ * same rules for both:
198
+ *
199
+ * Light: the preview's canvas, surface and rail as given; raised = surface;
200
+ * sunken = canvas 25% toward the rail; hover = surface 10% toward the rail;
201
+ * titlebar = surface 35% toward the canvas; the borders are Figma's Aglyn
202
+ * mode's, 18% (subtle) and 22% (strong) toward the rail. Text, status, scrim
203
+ * and the danger fill are Figma's Aglyn mode's.
204
+ *
205
+ * Dark: Figma's Aglyn dark mode tinted toward the dark rail seed: canvas
206
+ * 22%, surface and raised 18%, rail 45%; everything else is that mode's.
207
+ *
208
+ * "Toward" is a straight per-channel sRGB blend, rounded to the byte.
209
+ */
210
+ export declare function deriveThemeFromPreview(preview: ThemePreview, darkRailSeed: string): {
211
+ light: ThemeColors;
212
+ dark: ThemeColors;
213
+ };
214
+ /** Every theme, in the order the Theme settings sheet lists them. */
215
+ export declare const THEME_PALETTES: readonly ThemePalette[];
216
+ /** The named accents, Figma's own values with their text shades. */
217
+ export declare const THEME_ACCENTS: readonly ThemeNamedAccent[];
218
+ /** The accent picker's swatches, in Figma's order. */
219
+ export declare const THEME_ACCENT_SWATCHES: readonly ThemeAccentSwatch[];
220
+ /**
221
+ * Every control's shade of one accent color (AGL-3950).
222
+ *
223
+ * A color one of Figma's Accent modes is drawn from (its ring) answers with
224
+ * that mode exactly: Figma wins where it defines a value. Any other color is
225
+ * derived:
226
+ *
227
+ * 1. White text on the color already reads (4.5:1): the fill is the color,
228
+ * `on` is white.
229
+ * 2. The color carries white text only at the large-text bar (3:1 up to
230
+ * 4.5:1) and near-black text reads on it at 4.5:1: the fill KEEPS the
231
+ * brand color and `on` flips to near-black, the color's own hue at 8%
232
+ * lightness. Darkening such a color far enough for white text moves it
233
+ * visibly off the brand; this is Figma's Pink (#E040FB, 3.34:1). The 3:1
234
+ * threshold is the one that sends Pink here and Blue (2.43:1) and the
235
+ * workspace green (2.99:1) to rule 3, as Figma draws them.
236
+ * 3. Otherwise the fill is the color darkened in 2% HSL-lightness steps until
237
+ * white reaches 4.5:1, and `on` is white.
238
+ *
239
+ * hover and pressed are the fill 4% and 8% darker (HSL lightness), soft is
240
+ * the color at 16% alpha, ring is the color, icon is the color darkened in 2%
241
+ * steps until it reaches 3:1 on the light surface, and the two text shades
242
+ * walk it (darker on light, lighter on dark) until 4.5:1 on that surface.
243
+ * Null for anything that is not `#RRGGBB`.
244
+ */
245
+ export declare function deriveAccent(color: string): ThemeAccent | null;
246
+ /** Figma's Density modes. */
247
+ export declare const THEME_DENSITIES: readonly ThemeDensity[];
248
+ /** A theme by id, Aglyn for anything unknown. */
249
+ export declare function themePalette(id: unknown): ThemePalette;