create-dfactory 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/package.json +50 -0
  4. package/templates/base/dfactory.config.ts +34 -0
  5. package/templates/react/src/templates/invoice/template.tsx +154 -0
  6. package/templates/react/src/templates/invoice-reference/components/InvoiceReferenceDocument.tsx +309 -0
  7. package/templates/react/src/templates/invoice-reference/components/InvoiceReferenceFooter.tsx +26 -0
  8. package/templates/react/src/templates/invoice-reference/components/InvoiceReferenceHeader.tsx +23 -0
  9. package/templates/react/src/templates/invoice-reference/components/InvoiceReferencePagination.tsx +24 -0
  10. package/templates/react/src/templates/invoice-reference/components/InvoiceReferenceToc.tsx +30 -0
  11. package/templates/react/src/templates/invoice-reference/components/InvoiceReferenceWatermark.tsx +16 -0
  12. package/templates/react/src/templates/invoice-reference/components/types.ts +65 -0
  13. package/templates/react/src/templates/invoice-reference/template.tsx +307 -0
  14. package/templates/vue/src/templates/invoice/InvoiceTemplate.vue +96 -0
  15. package/templates/vue/src/templates/invoice/template.ts +85 -0
  16. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferenceDocument.vue +241 -0
  17. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferenceFooter.vue +26 -0
  18. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferenceHeader.vue +25 -0
  19. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferencePagination.vue +24 -0
  20. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferenceToc.vue +34 -0
  21. package/templates/vue/src/templates/invoice-reference/components/InvoiceReferenceWatermark.vue +20 -0
  22. package/templates/vue/src/templates/invoice-reference/components/types.ts +65 -0
  23. package/templates/vue/src/templates/invoice-reference/template.ts +300 -0
  24. package/templates/vue/src/vue-shims.d.ts +6 -0
@@ -0,0 +1,30 @@
1
+ import type { TemplateTocHeading } from "@dfactory/core";
2
+
3
+ export function InvoiceReferenceToc(props: {
4
+ title: string;
5
+ headings: TemplateTocHeading[];
6
+ }) {
7
+ return (
8
+ <nav
9
+ aria-label={props.title}
10
+ style={{
11
+ marginBottom: "24px",
12
+ padding: "14px 16px",
13
+ borderRadius: "10px",
14
+ border: "1px solid rgba(79, 70, 229, 0.18)",
15
+ background: "rgba(79, 70, 229, 0.04)"
16
+ }}
17
+ >
18
+ <h2 style={{ margin: 0, fontSize: "16px", color: "#312e81" }}>{props.title}</h2>
19
+ <ol style={{ margin: "10px 0 0", paddingLeft: "18px" }}>
20
+ {props.headings.map((heading) => (
21
+ <li key={heading.id} style={{ marginTop: "4px", marginLeft: `${(heading.level - 1) * 10}px` }}>
22
+ <a href={`#${heading.id}`} style={{ color: "#1e293b", textDecoration: "none" }}>
23
+ {heading.text}
24
+ </a>
25
+ </li>
26
+ ))}
27
+ </ol>
28
+ </nav>
29
+ );
30
+ }
@@ -0,0 +1,16 @@
1
+ export function InvoiceReferenceWatermark(props: { text: string }) {
2
+ return (
3
+ <div
4
+ style={{
5
+ transform: "rotate(-24deg)",
6
+ fontSize: "52px",
7
+ fontWeight: 700,
8
+ letterSpacing: "0.08em",
9
+ color: "rgba(79, 70, 229, 0.14)",
10
+ textTransform: "uppercase"
11
+ }}
12
+ >
13
+ {props.text}
14
+ </div>
15
+ );
16
+ }
@@ -0,0 +1,65 @@
1
+ export interface InvoiceReferenceCompany {
2
+ name: string;
3
+ address: string;
4
+ email: string;
5
+ phone: string;
6
+ website: string;
7
+ taxId: string;
8
+ logoUrl?: string;
9
+ }
10
+
11
+ export interface InvoiceReferenceCustomer {
12
+ name: string;
13
+ contact: string;
14
+ email: string;
15
+ address: string;
16
+ }
17
+
18
+ export interface InvoiceReferenceLineItem {
19
+ id: string;
20
+ name: string;
21
+ description?: string;
22
+ qty: number;
23
+ unitPrice: number;
24
+ discount?: number;
25
+ taxRate?: number;
26
+ }
27
+
28
+ export interface InvoiceReferenceSection {
29
+ title: string;
30
+ description: string;
31
+ notes?: string;
32
+ }
33
+
34
+ export interface InvoiceReferencePayment {
35
+ iban: string;
36
+ swift: string;
37
+ bankName: string;
38
+ instructions?: string;
39
+ }
40
+
41
+ export interface InvoiceReferenceWatermark {
42
+ enabled: boolean;
43
+ text: string;
44
+ }
45
+
46
+ export interface InvoiceReferenceBrand {
47
+ accentColor?: string;
48
+ supportEmail?: string;
49
+ }
50
+
51
+ export interface InvoiceReferencePayload {
52
+ invoiceNumber: string;
53
+ purchaseOrder?: string;
54
+ issuedAt: string;
55
+ dueAt: string;
56
+ currency: string;
57
+ company: InvoiceReferenceCompany;
58
+ customer: InvoiceReferenceCustomer;
59
+ items: InvoiceReferenceLineItem[];
60
+ sections: InvoiceReferenceSection[];
61
+ payment: InvoiceReferencePayment;
62
+ notes?: string;
63
+ watermark?: InvoiceReferenceWatermark;
64
+ brand?: InvoiceReferenceBrand;
65
+ }
@@ -0,0 +1,307 @@
1
+ import { z } from "zod";
2
+
3
+ import { defineTemplate } from "@dfactory/template-kit";
4
+
5
+ import { InvoiceReferenceDocument } from "./components/InvoiceReferenceDocument";
6
+ import { InvoiceReferenceFooter } from "./components/InvoiceReferenceFooter";
7
+ import { InvoiceReferenceHeader } from "./components/InvoiceReferenceHeader";
8
+ import { InvoiceReferencePagination } from "./components/InvoiceReferencePagination";
9
+ import { InvoiceReferenceToc } from "./components/InvoiceReferenceToc";
10
+ import { InvoiceReferenceWatermark } from "./components/InvoiceReferenceWatermark";
11
+
12
+ const lineItemSchema = z.object({
13
+ id: z.string(),
14
+ name: z.string(),
15
+ description: z.string().optional(),
16
+ qty: z.number().positive(),
17
+ unitPrice: z.number().nonnegative(),
18
+ discount: z.number().nonnegative().max(100).optional(),
19
+ taxRate: z.number().nonnegative().max(100).optional()
20
+ });
21
+
22
+ const sectionSchema = z.object({
23
+ title: z.string(),
24
+ description: z.string(),
25
+ notes: z.string().optional()
26
+ });
27
+
28
+ const invoiceReferenceSchema = z.object({
29
+ invoiceNumber: z.string(),
30
+ purchaseOrder: z.string().optional(),
31
+ issuedAt: z.string(),
32
+ dueAt: z.string(),
33
+ currency: z.string(),
34
+ company: z.object({
35
+ name: z.string(),
36
+ address: z.string(),
37
+ email: z.string(),
38
+ phone: z.string(),
39
+ website: z.string(),
40
+ taxId: z.string(),
41
+ logoUrl: z.string().url().optional()
42
+ }),
43
+ customer: z.object({
44
+ name: z.string(),
45
+ contact: z.string(),
46
+ email: z.string(),
47
+ address: z.string()
48
+ }),
49
+ items: z.array(lineItemSchema).min(1),
50
+ sections: z.array(sectionSchema).min(1),
51
+ payment: z.object({
52
+ iban: z.string(),
53
+ swift: z.string(),
54
+ bankName: z.string(),
55
+ instructions: z.string().optional()
56
+ }),
57
+ notes: z.string().optional(),
58
+ watermark: z
59
+ .object({
60
+ enabled: z.boolean(),
61
+ text: z.string()
62
+ })
63
+ .optional(),
64
+ brand: z
65
+ .object({
66
+ accentColor: z.string().optional(),
67
+ supportEmail: z.string().optional()
68
+ })
69
+ .optional()
70
+ });
71
+
72
+ type InvoiceReferencePayload = z.infer<typeof invoiceReferenceSchema>;
73
+
74
+ function createItems(count: number): InvoiceReferencePayload["items"] {
75
+ return Array.from({ length: count }, (_, index) => {
76
+ const row = index + 1;
77
+ return {
78
+ id: `line-${row}`,
79
+ name: `Professional Service Block ${row}`,
80
+ description:
81
+ row % 2 === 0
82
+ ? "Includes discovery, implementation, and QA handoff."
83
+ : "Includes architecture review and stakeholder alignment.",
84
+ qty: (row % 3) + 1,
85
+ unitPrice: 180 + row * 12,
86
+ discount: row % 5 === 0 ? 8 : 0,
87
+ taxRate: 21
88
+ };
89
+ });
90
+ }
91
+
92
+ function createSections(count: number): InvoiceReferencePayload["sections"] {
93
+ return Array.from({ length: count }, (_, index) => {
94
+ const row = index + 1;
95
+ return {
96
+ title: `Delivery Milestone ${row}`,
97
+ description:
98
+ "This section demonstrates long-form print content with structured headings, making TOC and page breaks easy to validate during authoring.",
99
+ notes:
100
+ row % 2 === 0
101
+ ? "Attach acceptance notes and sign-off evidence for enterprise audits."
102
+ : "Use pagination markers for sections that should stay together."
103
+ };
104
+ });
105
+ }
106
+
107
+ function createPayload(options: {
108
+ invoiceNumber: string;
109
+ lineCount: number;
110
+ watermarkText: string;
111
+ accentColor: string;
112
+ }): InvoiceReferencePayload {
113
+ return {
114
+ invoiceNumber: options.invoiceNumber,
115
+ purchaseOrder: "PO-40218",
116
+ issuedAt: "2026-03-27",
117
+ dueAt: "2026-04-10",
118
+ currency: "EUR",
119
+ company: {
120
+ name: "DFactory Labs Ltd.",
121
+ address: "A. Briana Street 9A\nRiga, LV-1001\nLatvia",
122
+ email: "finance@dfactory.dev",
123
+ phone: "+371 6700 4500",
124
+ website: "https://dfactory.dev",
125
+ taxId: "LV40203577891"
126
+ },
127
+ customer: {
128
+ name: "Northwind Trading Group",
129
+ contact: "Marta Jensen",
130
+ email: "marta.jensen@northwind.example",
131
+ address: "28 Innovation Plaza\nTallinn, 10111\nEstonia"
132
+ },
133
+ items: createItems(options.lineCount),
134
+ sections: createSections(Math.max(4, Math.ceil(options.lineCount / 4))),
135
+ payment: {
136
+ iban: "LV80HABA0551045933178",
137
+ swift: "HABALV22",
138
+ bankName: "Swedbank AS",
139
+ instructions: "Please reference invoice number in payment details."
140
+ },
141
+ notes:
142
+ "All deliverables were accepted during sprint review. This reference template showcases advanced TOC, pagination markers, watermark layers, and custom header/footer element rendering.",
143
+ watermark: {
144
+ enabled: true,
145
+ text: options.watermarkText
146
+ },
147
+ brand: {
148
+ accentColor: options.accentColor,
149
+ supportEmail: "support@dfactory.dev"
150
+ }
151
+ };
152
+ }
153
+
154
+ const template = defineTemplate({
155
+ meta: {
156
+ id: "invoice-reference",
157
+ title: "Invoice Reference (Advanced)",
158
+ description:
159
+ "Rich multi-file reference template with first-class TOC/header/footer/watermark/pagination elements.",
160
+ framework: "react",
161
+ version: "1.0.0",
162
+ tags: ["billing", "reference", "advanced"]
163
+ },
164
+ schema: invoiceReferenceSchema,
165
+ pdf: {
166
+ page: {
167
+ size: "A4",
168
+ marginsMm: { top: 16, right: 12, bottom: 16, left: 12 }
169
+ },
170
+ toc: {
171
+ enabled: true,
172
+ maxDepth: 3,
173
+ title: "Invoice Reference Contents"
174
+ },
175
+ pagination: {
176
+ mode: "css"
177
+ },
178
+ headerFooter: {
179
+ enabled: true
180
+ },
181
+ assets: {
182
+ maxAssetCount: 24,
183
+ maxAssetBytes: 1024 * 1024,
184
+ timeoutMs: 4000
185
+ },
186
+ metadata: {
187
+ title: "DFactory Invoice Reference Document",
188
+ author: "DFactory",
189
+ keywords: ["invoice", "reference", "pdf", "dfactory"]
190
+ },
191
+ watermark: {
192
+ text: "DRAFT",
193
+ opacity: 0.12,
194
+ fontSize: 44
195
+ }
196
+ },
197
+ pdfElements: {
198
+ toc: {
199
+ render(context) {
200
+ return (
201
+ <InvoiceReferenceToc
202
+ title={`${context.template.title} TOC`}
203
+ headings={context.headings}
204
+ />
205
+ );
206
+ }
207
+ },
208
+ header: {
209
+ render(context) {
210
+ return (
211
+ <InvoiceReferenceHeader
212
+ title={context.template.title}
213
+ invoiceNumber={
214
+ (context.payload as InvoiceReferencePayload).invoiceNumber
215
+ }
216
+ generatedAtToken={context.tokens.date}
217
+ />
218
+ );
219
+ }
220
+ },
221
+ footer: {
222
+ render(context) {
223
+ return (
224
+ <InvoiceReferenceFooter
225
+ templateId={context.templateId}
226
+ pageNumberToken={context.tokens.pageNumber}
227
+ totalPagesToken={context.tokens.totalPages}
228
+ supportEmail={
229
+ (context.payload as InvoiceReferencePayload).brand?.supportEmail
230
+ }
231
+ />
232
+ );
233
+ }
234
+ },
235
+ watermark: {
236
+ render(context) {
237
+ const watermark = (context.payload as InvoiceReferencePayload).watermark;
238
+ if (!watermark?.enabled) {
239
+ return "";
240
+ }
241
+ return <InvoiceReferenceWatermark text={watermark.text} />;
242
+ }
243
+ },
244
+ pagination: {
245
+ render(context) {
246
+ return (
247
+ <InvoiceReferencePagination
248
+ pageNumberToken={context.tokens.pageNumber}
249
+ totalPagesToken={context.tokens.totalPages}
250
+ />
251
+ );
252
+ }
253
+ }
254
+ },
255
+ examples: [
256
+ {
257
+ name: "short",
258
+ description: "Single-page styled invoice with minimal line items.",
259
+ payload: createPayload({
260
+ invoiceNumber: "INV-REF-1001",
261
+ lineCount: 4,
262
+ watermarkText: "INTERNAL",
263
+ accentColor: "#4f46e5"
264
+ })
265
+ },
266
+ {
267
+ name: "multi-page",
268
+ description: "Long-form invoice designed to exercise TOC and pagination.",
269
+ payload: createPayload({
270
+ invoiceNumber: "INV-REF-1002",
271
+ lineCount: 24,
272
+ watermarkText: "REVIEW",
273
+ accentColor: "#3730a3"
274
+ })
275
+ },
276
+ {
277
+ name: "branded",
278
+ description: "Branded variation with strong accent and support metadata.",
279
+ payload: createPayload({
280
+ invoiceNumber: "INV-REF-1003",
281
+ lineCount: 12,
282
+ watermarkText: "BRANDED",
283
+ accentColor: "#1d4ed8"
284
+ })
285
+ },
286
+ {
287
+ name: "watermark-heavy",
288
+ description: "Watermark-forward profile to validate overlay readability.",
289
+ payload: createPayload({
290
+ invoiceNumber: "INV-REF-1004",
291
+ lineCount: 18,
292
+ watermarkText: "CONFIDENTIAL",
293
+ accentColor: "#4338ca"
294
+ })
295
+ }
296
+ ],
297
+ render(payload) {
298
+ return <InvoiceReferenceDocument payload={payload} />;
299
+ }
300
+ });
301
+
302
+ export const meta = template.meta;
303
+ export const schema = template.schema;
304
+ export const pdf = template.pdf;
305
+ export const pdfElements = template.pdfElements;
306
+ export const examples = template.examples;
307
+ export const render = template.render;
@@ -0,0 +1,96 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ import {
5
+ AvoidBreakInside,
6
+ Document,
7
+ Heading,
8
+ KeepWithNext,
9
+ NumericCell,
10
+ Page,
11
+ PageBreakBefore,
12
+ Paragraph,
13
+ Section,
14
+ Table,
15
+ TableBody,
16
+ TableCell,
17
+ TableHead,
18
+ TableHeaderCell,
19
+ TableRow
20
+ } from "@dfactory/pdf-primitives-vue";
21
+
22
+ interface InvoiceItem {
23
+ name: string;
24
+ qty: number;
25
+ price: number;
26
+ }
27
+
28
+ interface InvoicePayload {
29
+ invoiceNumber: string;
30
+ customerName: string;
31
+ issuedAt: string;
32
+ items: InvoiceItem[];
33
+ }
34
+
35
+ const props = defineProps<{
36
+ payload: InvoicePayload;
37
+ }>();
38
+
39
+ const total = computed(() => {
40
+ return props.payload.items.reduce((sum, item) => sum + item.qty * item.price, 0);
41
+ });
42
+ </script>
43
+
44
+ <template>
45
+ <Document>
46
+ <Page>
47
+ <Section :style="{ padding: '24px' }">
48
+ <KeepWithNext>
49
+ <Heading as="h1" :style="{ marginBottom: '8px', color: 'var(--df-pdf-color-accent)' }">
50
+ Invoice {{ props.payload.invoiceNumber }}
51
+ </Heading>
52
+ <Paragraph :style="{ color: 'var(--df-pdf-color-muted)', marginTop: 0 }">
53
+ Customer: {{ props.payload.customerName }}
54
+ </Paragraph>
55
+ <Paragraph :style="{ color: 'var(--df-pdf-color-muted)', marginTop: '4px' }">
56
+ Issued: {{ props.payload.issuedAt }}
57
+ </Paragraph>
58
+ </KeepWithNext>
59
+
60
+ <AvoidBreakInside>
61
+ <Heading as="h2" :style="{ marginTop: '20px', marginBottom: '8px', fontSize: '16px' }">
62
+ Line Items
63
+ </Heading>
64
+ <Table :style="{ marginTop: '10px' }">
65
+ <TableHead>
66
+ <TableRow>
67
+ <TableHeaderCell :style="{ textAlign: 'left' }">Item</TableHeaderCell>
68
+ <TableHeaderCell :style="{ textAlign: 'right' }">Qty</TableHeaderCell>
69
+ <TableHeaderCell :style="{ textAlign: 'right' }">Price</TableHeaderCell>
70
+ </TableRow>
71
+ </TableHead>
72
+ <TableBody>
73
+ <TableRow v-for="item in props.payload.items" :key="item.name">
74
+ <TableCell>{{ item.name }}</TableCell>
75
+ <NumericCell>{{ item.qty }}</NumericCell>
76
+ <NumericCell>${{ (item.price * item.qty).toFixed(2) }}</NumericCell>
77
+ </TableRow>
78
+ </TableBody>
79
+ </Table>
80
+
81
+ <Paragraph :style="{ textAlign: 'right', marginTop: '16px', fontWeight: 700 }">
82
+ Total: ${{ total.toFixed(2) }}
83
+ </Paragraph>
84
+ </AvoidBreakInside>
85
+
86
+ <PageBreakBefore>
87
+ <Heading as="h2" :style="{ marginTop: '24px', fontSize: '16px' }">Payment Terms</Heading>
88
+ <Paragraph :style="{ color: 'var(--df-pdf-color-text)', lineHeight: 1.6 }">
89
+ Payment due within 14 calendar days from invoice date. Late payments may incur additional
90
+ charges.
91
+ </Paragraph>
92
+ </PageBreakBefore>
93
+ </Section>
94
+ </Page>
95
+ </Document>
96
+ </template>
@@ -0,0 +1,85 @@
1
+ import { h } from "vue";
2
+ import { z } from "zod";
3
+
4
+ import { defineTemplate } from "@dfactory/template-kit";
5
+
6
+ import InvoiceTemplate from "./InvoiceTemplate.vue";
7
+
8
+ const template = defineTemplate({
9
+ meta: {
10
+ id: "invoice",
11
+ title: "Invoice",
12
+ description: "Default starter invoice template",
13
+ framework: "vue",
14
+ version: "1.0.0",
15
+ tags: ["billing", "starter"]
16
+ },
17
+ schema: z.object({
18
+ invoiceNumber: z.string(),
19
+ customerName: z.string(),
20
+ issuedAt: z.string(),
21
+ items: z.array(
22
+ z.object({
23
+ name: z.string(),
24
+ qty: z.number(),
25
+ price: z.number()
26
+ })
27
+ )
28
+ }),
29
+ pdf: {
30
+ page: {
31
+ size: "A4",
32
+ marginsMm: { top: 12, right: 12, bottom: 14, left: 12 }
33
+ },
34
+ toc: {
35
+ enabled: true,
36
+ maxDepth: 2,
37
+ title: "Invoice Overview"
38
+ },
39
+ pagination: {
40
+ mode: "css"
41
+ },
42
+ headerFooter: {
43
+ enabled: true,
44
+ footerTemplate:
45
+ "<div style=\"width:100%;font-size:9px;padding:0 12px;color:#64748b;display:flex;justify-content:space-between;\"><span>{{title}}</span><span>{{pageXofY}}</span></div>"
46
+ },
47
+ metadata: {
48
+ title: "Invoice Document",
49
+ keywords: ["invoice", "billing", "starter"]
50
+ },
51
+ theme: {
52
+ font: {
53
+ family: "Inter, 'Segoe UI', sans-serif"
54
+ },
55
+ color: {
56
+ accent: "#1d4ed8"
57
+ }
58
+ }
59
+ },
60
+ examples: [
61
+ {
62
+ name: "default",
63
+ payload: {
64
+ invoiceNumber: "INV-1001",
65
+ customerName: "Northwind Trading",
66
+ issuedAt: "2026-03-27",
67
+ items: [
68
+ { name: "Consulting", qty: 2, price: 420 },
69
+ { name: "Support", qty: 1, price: 180 }
70
+ ]
71
+ }
72
+ }
73
+ ],
74
+ render(payload) {
75
+ return h(InvoiceTemplate, {
76
+ payload
77
+ });
78
+ }
79
+ });
80
+
81
+ export const meta = template.meta;
82
+ export const schema = template.schema;
83
+ export const pdf = template.pdf;
84
+ export const examples = template.examples;
85
+ export const render = template.render;