1// DF-1: the single source of truth for design-family identity, replacing 2// the previously hardcoded `{ledger,banner,postmark}` maps duplicated 3// across src/app/main.js, src/sample-render.js, and 4// src/features/product-events/product-events.js (seam map: 5// context/baseline/design-family-renderer-df-0-seam-map-2026-09-25.md §2.4-2.6). 6// 7// Scope boundary (deliberate, not an oversight): this registry declares all 8// 8 canonical families the epic names (§1/§4.1 of the initiative), now that 9// DF-5 has shipped the last three. `essential`/`modern`/`studio` 10// are the direct migration targets of the legacy `ledger`/`banner`/ 11// `postmark` templateId values (BC-1 in 12// context/specs/initiative-design-family-renderer-refactor.md); their 13// renderer functions still live in ledger.js/banner.js/postmark.js â those 14// file/function names were never renamed to match the family ids (see DF-3 15// seam-map §13 for why), but their *output* is not a frozen 1:1 copy of the 16// pre-initiative Ledger/Banner/Postmark renderers: DF-3 redesigned Studio 17// (postmark.js) into an actual brand/logo-forward family per the 18// initiative's family contracts (§5), while Essential/Modern 19// (ledger.js/banner.js) were left unchanged because they already satisfied 20// their contracts. `trades`/`compact` (DF-4) and `professional`/`corporate`/ 21// `nordic` (DF-5) have no legacy templateId â 22// they are genuinely new families with no pre-initiative equivalent, hence 23// `legacyTemplateId: null` below â and their renderers live in 24// trades.js/compact.js/professional.js/corporate.js/nordic.js, named to 25// match their family ids from the start since there is no legacy-import 26// constraint holding those names back the way there is for 27// ledger.js/banner.js/postmark.js. 28// 29// Do not confuse a design family with an acquisition/profession starter 30// (freelancer, consultant, contractor, ...). Those are a disjoint concept â 31// see src/features/editor-launch/launch-intent.js and 32// src/features/invoice-presets/presets.js's `recommendedDesignFamilyId`. 33// 34// Import boundary: identity/validation/migration (no renderer dependency) 35// lives in ./design-family-ids.js and is re-exported below unchanged. Only 36// import this module (design-family-registry.js) from a call site that 37// genuinely needs a renderer function or the full DESIGN_FAMILY_LIST (today 38// that's src/app/main.js and src/sample-render.js). Every other consumer â 39// analytics, document-model defaults, workspace validation/migration, 40// backup migration â should import design-family-ids.js directly to avoid 41// pulling the renderer stack into an otherwise-lightweight bundle. 42 43import { renderLedgerTemplate } from '../templates/ledger.6d0f71248a24.js'; 44import { renderBannerTemplate } from '../templates/banner.be470368f4b3.js'; 45import { renderPostmarkTemplate } from '../templates/postmark.f94435293b04.js'; 46import { renderTradesTemplate } from '../templates/trades.a9a0c5721425.js'; 47import { renderCompactTemplate } from '../templates/compact.b6c80b974441.js'; 48import { renderProfessionalTemplate } from '../templates/professional.e091e342dabc.js'; 49import { renderCorporateTemplate } from '../templates/corporate.5518a886e119.js'; 50import { renderNordicTemplate } from '../templates/nordic.fce82c834f7f.js'; 51import { 52 DESIGN_FAMILY_KEYS, 53 DEFAULT_DESIGN_FAMILY_ID, 54 LEGACY_TEMPLATE_ID_TO_DESIGN_FAMILY_ID, 55 isValidDesignFamilyId, 56 migrateLegacyTemplateId 57} from './design-family-ids.0d96e91b8a3b.js'; 58 59export { 60 DESIGN_FAMILY_KEYS, 61 DEFAULT_DESIGN_FAMILY_ID, 62 LEGACY_TEMPLATE_ID_TO_DESIGN_FAMILY_ID, 63 isValidDesignFamilyId, 64 migrateLegacyTemplateId 65}; 66 67export const DESIGN_FAMILY_LIST = Object.freeze([ 68 Object.freeze({ 69 id: 'essential', 70 legacyTemplateId: 'ledger', 71 labelKey: 'editor.option.template.ledger', 72 iconKey: 'layout-ledger', 73 analyticsClass: 'essential', 74 render: renderLedgerTemplate, 75 status: 'available' 76 }), 77 Object.freeze({ 78 id: 'modern', 79 legacyTemplateId: 'banner', 80 labelKey: 'editor.option.template.banner', 81 iconKey: 'layout-banner', 82 analyticsClass: 'modern', 83 render: renderBannerTemplate, 84 status: 'available' 85 }), 86 Object.freeze({ 87 id: 'studio', 88 legacyTemplateId: 'postmark', 89 labelKey: 'editor.option.template.postmark', 90 iconKey: 'layout-postmark', 91 analyticsClass: 'studio', 92 render: renderPostmarkTemplate, 93 status: 'available' 94 }), 95 Object.freeze({ 96 id: 'trades', 97 legacyTemplateId: null, 98 labelKey: 'editor.option.template.trades', 99 iconKey: 'layout-trades', 100 analyticsClass: 'trades', 101 render: renderTradesTemplate, 102 status: 'available' 103 }), 104 Object.freeze({ 105 id: 'compact', 106 legacyTemplateId: null, 107 labelKey: 'editor.option.template.compact', 108 iconKey: 'layout-compact', 109 analyticsClass: 'compact', 110 render: renderCompactTemplate, 111 status: 'available' 112 }), 113 Object.freeze({ 114 id: 'professional', 115 legacyTemplateId: null, 116 labelKey: 'editor.option.template.professional', 117 iconKey: 'layout-professional', 118 analyticsClass: 'professional', 119 render: renderProfessionalTemplate, 120 status: 'available' 121 }), 122 Object.freeze({ 123 id: 'corporate', 124 legacyTemplateId: null, 125 labelKey: 'editor.option.template.corporate', 126 iconKey: 'layout-corporate', 127 analyticsClass: 'corporate', 128 render: renderCorporateTemplate, 129 status: 'available' 130 }), 131 Object.freeze({ 132 id: 'nordic', 133 legacyTemplateId: null, 134 labelKey: 'editor.option.template.nordic', 135 iconKey: 'layout-nordic', 136 analyticsClass: 'nordic', 137 render: renderNordicTemplate, 138 status: 'available' 139 }) 140]); 141 142export function getDesignFamily(id) { 143 return DESIGN_FAMILY_LIST.find((family) => family.id === id) || null; 144} 145 146/** Never returns null/undefined â falls back to the default family, mirroring the 147 * current dispatch's existing "unknown value -> Ledger" fallback behavior. */ 148export function getRendererForDesignFamily(id) { 149 return getDesignFamily(id)?.render || getDesignFamily(DEFAULT_DESIGN_FAMILY_ID).render; 150}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.