PageSourceSearch

https://invoicecraftly.com/_assets/js/features/design-families/design-family-registry.1815ef906fd4.js

js invoicecraftly.com collected 2026-10-02 01:34:51 UTC 6,067 bytes, 150 lines download raw bytes

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.