agentic-mermaid 0.1.0 → 0.1.2
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.
- package/CHANGELOG.md +149 -4
- package/LICENSES/Apache-2.0.txt +202 -0
- package/README.md +25 -32
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/assets/fonts/FONT-LICENSES.md +9 -5
- package/assets/fonts/Inter-Bold.ttf +0 -0
- package/assets/fonts/Inter-Medium.ttf +0 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/Inter-SemiBold.ttf +0 -0
- package/dist/agent-core.d.ts +463 -0
- package/dist/agent-core.js +397 -0
- package/dist/agent.d.ts +81 -1822
- package/dist/agent.js +336 -36839
- package/dist/agentic-mermaid-mcp.js +7 -37908
- package/dist/am.js +33638 -36261
- package/dist/chunk-4QECACIA.js +4702 -0
- package/dist/chunk-CDPKJ2BQ.js +37 -0
- package/dist/chunk-QKDLMOJJ.js +3487 -0
- package/dist/chunk-WI35L7IR.js +615 -0
- package/dist/chunk-WN3YDOBG.js +149 -0
- package/dist/chunk-ZYMMKQ3I.js +62637 -0
- package/dist/index-D54dqSdC.d.ts +6777 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +310 -32836
- package/dist/mcp-cli-SBQSTJFC.js +17 -0
- package/docs/README.md +14 -6
- package/docs/schemas/style-spec.schema.json +1221 -30
- package/examples/styles/catalog.json +54 -0
- package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
- package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
- package/examples/styles/cupertino-prototype.mmd +10 -0
- package/examples/styles/cupertino-prototype.style.json +63 -0
- package/examples/styles/mid-century-report.style.json +2 -2
- package/examples/styles/star-chart-atlas.style.json +2 -1
- package/examples/styles/transit-route-map.style.json +2 -2
- package/examples/styles/vercel-inspired-prototype.mmd +6 -0
- package/examples/styles/vercel-inspired-prototype.style.json +87 -0
- package/package.json +70 -43
- package/server.json +41 -0
- package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
- package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
- package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
- package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
- package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
- package/AGENT_NATIVE.md +0 -602
- package/Instructions_for_agents.md +0 -83
- package/TODO.md +0 -662
- package/assets/hero.png +0 -0
- package/dist/index-x2Cj1dVv.d.ts +0 -1089
- package/docs/agent-api-cookbook.md +0 -308
- package/docs/agent-mutation-policy.md +0 -104
- package/docs/agent-workflow-examples.md +0 -46
- package/docs/api.md +0 -203
- package/docs/ascii.md +0 -103
- package/docs/assets/improvements/box-start-connector.png +0 -0
- package/docs/assets/improvements/comment-dropped-lint.png +0 -0
- package/docs/assets/improvements/er-content-loss.png +0 -0
- package/docs/assets/improvements/fan-in-trunks.png +0 -0
- package/docs/assets/improvements/gantt-family.png +0 -0
- package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
- package/docs/assets/improvements/gantt-verify-seam.png +0 -0
- package/docs/assets/improvements/subgraph-container-edges.png +0 -0
- package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
- package/docs/assets/improvements/wrapper-init-directive.png +0 -0
- package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
- package/docs/assets/style-cookbook/mid-century-report.png +0 -0
- package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
- package/docs/assets/style-cookbook/transit-route-map.png +0 -0
- package/docs/comparison.md +0 -94
- package/docs/config.md +0 -105
- package/docs/contributing/adding-diagram-types.md +0 -144
- package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
- package/docs/contributing/diagram-family-citizenship.md +0 -82
- package/docs/contributing/harvesting-upstream-tests.md +0 -126
- package/docs/contributing/lessons-learned.md +0 -276
- package/docs/contributing/releasing.md +0 -71
- package/docs/contributing/visual-review-evidence.md +0 -53
- package/docs/custom-style-cookbook.md +0 -154
- package/docs/design/families/README.md +0 -26
- package/docs/design/families/architecture-beta.md +0 -48
- package/docs/design/families/flowchart-parser-conformance.md +0 -22
- package/docs/design/families/gantt-research.md +0 -137
- package/docs/design/families/gantt.md +0 -329
- package/docs/design/families/journey-agentic-cards-before.png +0 -0
- package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
- package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
- package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
- package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
- package/docs/design/families/journey-migration-parity.md +0 -433
- package/docs/design/families/journey-usage-research.md +0 -423
- package/docs/design/families/journey.md +0 -125
- package/docs/design/families/xychart.md +0 -85
- package/docs/design/system/README.md +0 -45
- package/docs/design/system/abstraction-audit.md +0 -224
- package/docs/design/system/abstraction-recommendations.md +0 -655
- package/docs/design/system/architecture.mmd +0 -29
- package/docs/design/system/architecture.svg +0 -137
- package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
- package/docs/design/system/layout-rubric.md +0 -138
- package/docs/design/system/route-contracts.md +0 -848
- package/docs/design/system/source-preservation-ladder.md +0 -52
- package/docs/design/system/styles-rollout.md +0 -216
- package/docs/design/system/ugly-layouts.md +0 -119
- package/docs/diagram-families.md +0 -193
- package/docs/features.md +0 -147
- package/docs/fork-differences.md +0 -130
- package/docs/getting-started.md +0 -175
- package/docs/issue-derived-test-cases.md +0 -156
- package/docs/layout-characterization/README.md +0 -245
- package/docs/layout-characterization/contact-sheet-families.md +0 -496
- package/docs/layout-characterization/contact-sheet.md +0 -638
- package/docs/layout-characterization/properties.md +0 -281
- package/docs/layout-characterization/visual-quality.md +0 -160
- package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
- package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
- package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
- package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
- package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
- package/docs/layout-characterization/visual-snapshots/journey.svg +0 -118
- package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
- package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
- package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
- package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
- package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
- package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
- package/docs/mcp-code-mode-rationale.md +0 -101
- package/docs/mcp-http-transport.md +0 -223
- package/docs/mermaid-layout-complaints.md +0 -837
- package/docs/mutation-testing.md +0 -206
- package/docs/project/divergences.md +0 -98
- package/docs/project/dogfooding-docs-strategy.md +0 -66
- package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
- package/docs/project/lessons-learned.md +0 -1019
- package/docs/project/remove-role-styling-plan.md +0 -176
- package/docs/quality.md +0 -212
- package/docs/react.md +0 -97
- package/docs/style-authoring.md +0 -133
- package/docs/testing-strategy.md +0 -335
- package/docs/theming.md +0 -162
- package/examples/agent-improve-auth-flow.ts +0 -206
- package/examples/agent-loop.ts +0 -53
- package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
- package/llms.txt +0 -104
- package/skill-evals/README.md +0 -77
- package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
- package/skill-evals/fixtures/class-payment/input.mmd +0 -4
- package/skill-evals/fixtures/er-orders/input.mmd +0 -10
- package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
- package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
- package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
- package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
- package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
- package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
- package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
- package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
- package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
- package/skill-evals/shared-benchmark.json +0 -510
- package/src/agent/analyze.ts +0 -157
- package/src/agent/apply.ts +0 -146
- package/src/agent/architecture-body.ts +0 -458
- package/src/agent/certificates.ts +0 -110
- package/src/agent/class-body.ts +0 -319
- package/src/agent/core.ts +0 -207
- package/src/agent/create.ts +0 -106
- package/src/agent/describe.ts +0 -364
- package/src/agent/er-body.ts +0 -224
- package/src/agent/facts.ts +0 -337
- package/src/agent/families-builtin.ts +0 -934
- package/src/agent/families.ts +0 -232
- package/src/agent/family-layouts.ts +0 -826
- package/src/agent/flowchart-body.ts +0 -372
- package/src/agent/flowchart-unsupported.ts +0 -243
- package/src/agent/gantt-body.ts +0 -495
- package/src/agent/index.ts +0 -10
- package/src/agent/journey-body.ts +0 -414
- package/src/agent/label-metrics.ts +0 -28
- package/src/agent/layout-to-rendered.ts +0 -63
- package/src/agent/mutate.ts +0 -97
- package/src/agent/mutation-ops.ts +0 -51
- package/src/agent/op-schema.ts +0 -439
- package/src/agent/parse.ts +0 -223
- package/src/agent/pie-body.ts +0 -270
- package/src/agent/png.ts +0 -117
- package/src/agent/quadrant-body.ts +0 -336
- package/src/agent/quality.ts +0 -363
- package/src/agent/readability-audit.ts +0 -92
- package/src/agent/rendered-route-audit.ts +0 -61
- package/src/agent/sequence-body.ts +0 -345
- package/src/agent/serialize.ts +0 -214
- package/src/agent/state-body.ts +0 -589
- package/src/agent/structural-count.ts +0 -150
- package/src/agent/timeline-body.ts +0 -280
- package/src/agent/trace-log.ts +0 -43
- package/src/agent/types.ts +0 -979
- package/src/agent/verify.ts +0 -571
- package/src/agent/xychart-body.ts +0 -472
- package/src/architecture/config.ts +0 -282
- package/src/architecture/layout.ts +0 -496
- package/src/architecture/parser.ts +0 -375
- package/src/architecture/renderer.ts +0 -611
- package/src/architecture/types.ts +0 -113
- package/src/ascii/ansi.ts +0 -423
- package/src/ascii/architecture.ts +0 -210
- package/src/ascii/canvas.ts +0 -443
- package/src/ascii/class-diagram.ts +0 -697
- package/src/ascii/converter.ts +0 -475
- package/src/ascii/draw.ts +0 -1693
- package/src/ascii/edge-bundling.ts +0 -328
- package/src/ascii/edge-routing.ts +0 -330
- package/src/ascii/er-diagram.ts +0 -439
- package/src/ascii/gantt.ts +0 -276
- package/src/ascii/grid.ts +0 -747
- package/src/ascii/index.ts +0 -196
- package/src/ascii/journey.ts +0 -189
- package/src/ascii/meta.ts +0 -244
- package/src/ascii/multiline-utils.ts +0 -80
- package/src/ascii/pathfinder.ts +0 -301
- package/src/ascii/pie.ts +0 -67
- package/src/ascii/quadrant.ts +0 -158
- package/src/ascii/reverse.ts +0 -216
- package/src/ascii/sequence.ts +0 -499
- package/src/ascii/shapes/circle.ts +0 -27
- package/src/ascii/shapes/corners.ts +0 -143
- package/src/ascii/shapes/diamond.ts +0 -27
- package/src/ascii/shapes/hexagon.ts +0 -27
- package/src/ascii/shapes/index.ts +0 -106
- package/src/ascii/shapes/rectangle.ts +0 -168
- package/src/ascii/shapes/rounded.ts +0 -27
- package/src/ascii/shapes/special.ts +0 -332
- package/src/ascii/shapes/stadium.ts +0 -110
- package/src/ascii/shapes/state.ts +0 -192
- package/src/ascii/shapes/types.ts +0 -73
- package/src/ascii/timeline.ts +0 -128
- package/src/ascii/types.ts +0 -312
- package/src/ascii/validate.ts +0 -120
- package/src/ascii/width.ts +0 -81
- package/src/ascii/xychart.ts +0 -919
- package/src/browser.ts +0 -29
- package/src/class/layout.ts +0 -240
- package/src/class/parser.ts +0 -332
- package/src/class/renderer.ts +0 -638
- package/src/class/types.ts +0 -129
- package/src/cli/agent-instructions.ts +0 -1
- package/src/cli/am-bin.ts +0 -6
- package/src/cli/exit-codes.ts +0 -18
- package/src/cli/index.ts +0 -1117
- package/src/cli/init-agent.ts +0 -147
- package/src/color-resolver.ts +0 -152
- package/src/elk-instance.ts +0 -114
- package/src/er/layout.ts +0 -187
- package/src/er/parser.ts +0 -226
- package/src/er/renderer.ts +0 -792
- package/src/er/types.ts +0 -99
- package/src/font-manifest.ts +0 -27
- package/src/gantt/layout.ts +0 -365
- package/src/gantt/parser.ts +0 -282
- package/src/gantt/pipeline.ts +0 -27
- package/src/gantt/renderer.ts +0 -414
- package/src/gantt/schedule.ts +0 -513
- package/src/gantt/types.ts +0 -255
- package/src/index.ts +0 -368
- package/src/journey/layout.ts +0 -520
- package/src/journey/parser.ts +0 -218
- package/src/journey/renderer.ts +0 -811
- package/src/journey/types.ts +0 -144
- package/src/layout/geometry.ts +0 -182
- package/src/layout/pass.ts +0 -142
- package/src/layout/passes/index.ts +0 -3916
- package/src/layout-engine.ts +0 -1565
- package/src/layout-rubric.ts +0 -659
- package/src/mcp/artifacts.ts +0 -137
- package/src/mcp/dynamic-harness.ts +0 -31
- package/src/mcp/dynamic-modules.d.ts +0 -7
- package/src/mcp/facade.ts +0 -608
- package/src/mcp/harness-runtime.ts +0 -203
- package/src/mcp/hosted-server.ts +0 -468
- package/src/mcp/mcp-bin.ts +0 -3
- package/src/mcp/mcp-cli.ts +0 -82
- package/src/mcp/protocol.ts +0 -13
- package/src/mcp/sandbox.ts +0 -195
- package/src/mcp/sdk-decl.ts +0 -387
- package/src/mcp/server.ts +0 -362
- package/src/mcp/tool-surface.ts +0 -146
- package/src/mermaid-source.ts +0 -655
- package/src/multiline-utils.ts +0 -228
- package/src/parser.ts +0 -1031
- package/src/pie/layout.ts +0 -168
- package/src/pie/parser.ts +0 -136
- package/src/pie/renderer.ts +0 -234
- package/src/pie/types.ts +0 -82
- package/src/quadrant/layout.ts +0 -191
- package/src/quadrant/parser.ts +0 -183
- package/src/quadrant/renderer.ts +0 -322
- package/src/quadrant/types.ts +0 -113
- package/src/render-family-hooks.ts +0 -244
- package/src/renderer.ts +0 -1099
- package/src/route-contracts.ts +0 -2723
- package/src/scene/backend.ts +0 -76
- package/src/scene/fidelity.ts +0 -183
- package/src/scene/hybrid-backend.ts +0 -174
- package/src/scene/ir.ts +0 -181
- package/src/scene/marks.ts +0 -127
- package/src/scene/rough-backend.ts +0 -378
- package/src/scene/seed.ts +0 -46
- package/src/scene/style-registry.ts +0 -556
- package/src/sequence/layout.ts +0 -456
- package/src/sequence/parser.ts +0 -255
- package/src/sequence/renderer.ts +0 -604
- package/src/sequence/types.ts +0 -154
- package/src/shape-clipping.ts +0 -351
- package/src/shared/accessibility-directives.ts +0 -22
- package/src/shared/batched.ts +0 -61
- package/src/shared/color-math.ts +0 -72
- package/src/shared/svg-a11y.ts +0 -29
- package/src/shared/syntax-error.ts +0 -17
- package/src/shared/unicode-ranges.ts +0 -135
- package/src/styles.ts +0 -318
- package/src/svg-paths.ts +0 -28
- package/src/text-metrics.ts +0 -248
- package/src/theme.ts +0 -639
- package/src/timeline/layout.ts +0 -381
- package/src/timeline/parser.ts +0 -215
- package/src/timeline/renderer.ts +0 -538
- package/src/timeline/types.ts +0 -105
- package/src/types.ts +0 -454
- package/src/website-worker-modules.d.ts +0 -18
- package/src/xychart/axis-utils.ts +0 -109
- package/src/xychart/colors.ts +0 -124
- package/src/xychart/config.ts +0 -88
- package/src/xychart/layout.ts +0 -656
- package/src/xychart/parser.ts +0 -504
- package/src/xychart/renderer.ts +0 -640
- package/src/xychart/types.ts +0 -282
package/src/er/types.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// ER diagram types
|
|
3
|
-
//
|
|
4
|
-
// Models the parsed and positioned representations of a Mermaid ER diagram.
|
|
5
|
-
// ER diagrams show database entities, their attributes, and relationships.
|
|
6
|
-
// ============================================================================
|
|
7
|
-
|
|
8
|
-
import type { PositionedDiagram } from '../types.ts'
|
|
9
|
-
|
|
10
|
-
/** Parsed ER diagram — logical structure from mermaid text */
|
|
11
|
-
export interface ErDiagram {
|
|
12
|
-
/** Optional accessibility title (Mermaid accTitle) */
|
|
13
|
-
accessibilityTitle?: string
|
|
14
|
-
/** Optional accessibility description (Mermaid accDescr) */
|
|
15
|
-
accessibilityDescription?: string
|
|
16
|
-
/** All entity definitions */
|
|
17
|
-
entities: ErEntity[]
|
|
18
|
-
/** Relationships between entities */
|
|
19
|
-
relationships: ErRelationship[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface ErEntity {
|
|
23
|
-
id: string
|
|
24
|
-
/** Display name (same as id unless aliased) */
|
|
25
|
-
label: string
|
|
26
|
-
/** Entity attributes (columns) */
|
|
27
|
-
attributes: ErAttribute[]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ErAttribute {
|
|
31
|
-
/** Data type (string, int, varchar, etc.) */
|
|
32
|
-
type: string
|
|
33
|
-
/** Attribute name */
|
|
34
|
-
name: string
|
|
35
|
-
/** Key constraints: PK, FK, UK */
|
|
36
|
-
keys: Array<'PK' | 'FK' | 'UK'>
|
|
37
|
-
/** Optional comment */
|
|
38
|
-
comment?: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Cardinality notation (crow's foot):
|
|
43
|
-
* 'one' || exactly one
|
|
44
|
-
* 'zero-one' |o zero or one
|
|
45
|
-
* 'many' }| one or more
|
|
46
|
-
* 'zero-many' o{ zero or more
|
|
47
|
-
*/
|
|
48
|
-
export type Cardinality = 'one' | 'zero-one' | 'many' | 'zero-many'
|
|
49
|
-
|
|
50
|
-
export interface ErRelationship {
|
|
51
|
-
entity1: string
|
|
52
|
-
entity2: string
|
|
53
|
-
/** Cardinality at entity1's end */
|
|
54
|
-
cardinality1: Cardinality
|
|
55
|
-
/** Cardinality at entity2's end */
|
|
56
|
-
cardinality2: Cardinality
|
|
57
|
-
/** Relationship verb/label (e.g., "places", "contains") */
|
|
58
|
-
label: string
|
|
59
|
-
/** Whether the relationship is identifying (solid line) or non-identifying (dashed) */
|
|
60
|
-
identifying: boolean
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ============================================================================
|
|
64
|
-
// Positioned ER diagram — ready for SVG rendering
|
|
65
|
-
// ============================================================================
|
|
66
|
-
|
|
67
|
-
export interface PositionedErDiagram extends PositionedDiagram {
|
|
68
|
-
width: number
|
|
69
|
-
height: number
|
|
70
|
-
accessibilityTitle?: string
|
|
71
|
-
accessibilityDescription?: string
|
|
72
|
-
entities: PositionedErEntity[]
|
|
73
|
-
relationships: PositionedErRelationship[]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface PositionedErEntity {
|
|
77
|
-
id: string
|
|
78
|
-
label: string
|
|
79
|
-
attributes: ErAttribute[]
|
|
80
|
-
x: number
|
|
81
|
-
y: number
|
|
82
|
-
width: number
|
|
83
|
-
height: number
|
|
84
|
-
/** Height of the header row */
|
|
85
|
-
headerHeight: number
|
|
86
|
-
/** Height per attribute row */
|
|
87
|
-
rowHeight: number
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface PositionedErRelationship {
|
|
91
|
-
entity1: string
|
|
92
|
-
entity2: string
|
|
93
|
-
cardinality1: Cardinality
|
|
94
|
-
cardinality2: Cardinality
|
|
95
|
-
label: string
|
|
96
|
-
identifying: boolean
|
|
97
|
-
/** Path points from entity1 to entity2 */
|
|
98
|
-
points: Array<{ x: number; y: number }>
|
|
99
|
-
}
|
package/src/font-manifest.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export interface HostedFontFace {
|
|
2
|
-
family: string
|
|
3
|
-
file: string
|
|
4
|
-
weight: string
|
|
5
|
-
style: string
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const HOSTED_FONT_FACES: readonly HostedFontFace[] = [
|
|
9
|
-
{ family: 'Caveat', file: 'Caveat.ttf', weight: '400 700', style: 'normal' },
|
|
10
|
-
{ family: 'EB Garamond', file: 'EBGaramond.ttf', weight: '400 700', style: 'normal' },
|
|
11
|
-
{ family: 'Architects Daughter', file: 'ArchitectsDaughter.ttf', weight: '400', style: 'normal' },
|
|
12
|
-
{ family: 'Share Tech Mono', file: 'ShareTechMono.ttf', weight: '400', style: 'normal' },
|
|
13
|
-
{ family: 'DejaVu Sans', file: 'DejaVuSans.ttf', weight: '400', style: 'normal' },
|
|
14
|
-
{ family: 'DejaVu Sans', file: 'DejaVuSans-Bold.ttf', weight: '700', style: 'normal' },
|
|
15
|
-
]
|
|
16
|
-
|
|
17
|
-
export const HOSTED_FONT_FILES = [...new Set(HOSTED_FONT_FACES.map((font) => font.file))] as readonly string[]
|
|
18
|
-
|
|
19
|
-
function cssString(value: string): string {
|
|
20
|
-
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function hostedFontFaceCss(prefix = '/fonts/'): string {
|
|
24
|
-
return HOSTED_FONT_FACES.map((font) =>
|
|
25
|
-
`@font-face { font-family: '${cssString(font.family)}'; src: url('${prefix}${font.file}') format('truetype'); font-weight: ${font.weight}; font-style: ${font.style}; font-display: swap; }`,
|
|
26
|
-
).join('\n')
|
|
27
|
-
}
|
package/src/gantt/layout.ts
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// Gantt layout — schedule → deterministic geometry (docs/design/families/gantt.md §4).
|
|
3
|
-
//
|
|
4
|
-
// One layout model feeds both renderers: the SVG renderer consumes the pixel
|
|
5
|
-
// geometry directly; the ASCII renderer reuses tick *selection* (the resolved
|
|
6
|
-
// tick instants) and the row model with its own column math. Bars never
|
|
7
|
-
// leave the plot area; `vert` markers consume no task row; compact mode packs
|
|
8
|
-
// non-overlapping tasks of a section into shared rows deterministically
|
|
9
|
-
// (first-fit by source order).
|
|
10
|
-
// ============================================================================
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
GanttModel, GanttSchedule, GanttLayoutResult, GanttBarLayout, GanttRowLayout,
|
|
14
|
-
GanttSectionBand, GanttVertLayout, GanttTick, GanttTickUnit, EpochMs,
|
|
15
|
-
} from './types.ts'
|
|
16
|
-
import { DAY_MS, dayOfWeek, WEEKDAY_INDEX, formatGanttInstant, startOfDay } from './schedule.ts'
|
|
17
|
-
import { applyTextTransform, estimateTextWidth, resolveRenderStyle, STROKE_WIDTHS } from '../styles.ts'
|
|
18
|
-
import type { RenderStyleDefaults, ResolvedRenderStyle } from '../styles.ts'
|
|
19
|
-
import type { RenderOptions } from '../types.ts'
|
|
20
|
-
|
|
21
|
-
export const GANTT_MAX_TICKS = 120
|
|
22
|
-
|
|
23
|
-
export interface GanttLayoutOptions {
|
|
24
|
-
/** Total drawing width; the plot shrinks to fit. */
|
|
25
|
-
width?: number
|
|
26
|
-
compact?: boolean
|
|
27
|
-
barHeight?: number
|
|
28
|
-
/** Resolved clock instant (schedule.today). */
|
|
29
|
-
today?: EpochMs
|
|
30
|
-
/** Render options whose style roles affect label and axis geometry. */
|
|
31
|
-
renderOptions?: RenderOptions
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const GL = {
|
|
35
|
-
plotWidth: 600,
|
|
36
|
-
padding: 16,
|
|
37
|
-
titleHeight: 34,
|
|
38
|
-
axisHeight: 24,
|
|
39
|
-
rowGap: 8,
|
|
40
|
-
sectionGap: 6,
|
|
41
|
-
barHeight: 22,
|
|
42
|
-
labelGap: 12,
|
|
43
|
-
labelFontSize: 13,
|
|
44
|
-
sectionFontSize: 13,
|
|
45
|
-
} as const
|
|
46
|
-
|
|
47
|
-
export const GANTT_STYLE_DEFAULTS: RenderStyleDefaults = {
|
|
48
|
-
nodeLabelFontSize: GL.labelFontSize,
|
|
49
|
-
edgeLabelFontSize: 11,
|
|
50
|
-
groupHeaderFontSize: GL.sectionFontSize,
|
|
51
|
-
nodeLabelFontWeight: 500,
|
|
52
|
-
edgeLabelFontWeight: 500,
|
|
53
|
-
groupHeaderFontWeight: 600,
|
|
54
|
-
nodePaddingX: 0,
|
|
55
|
-
nodePaddingY: 0,
|
|
56
|
-
nodeLineWidth: STROKE_WIDTHS.innerBox,
|
|
57
|
-
edgeLineWidth: STROKE_WIDTHS.connector,
|
|
58
|
-
groupCornerRadius: 0,
|
|
59
|
-
groupPaddingX: 0,
|
|
60
|
-
groupPaddingY: 0,
|
|
61
|
-
groupLineWidth: STROKE_WIDTHS.outerBox,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const TICK_UNIT_MS: Record<GanttTickUnit, number> = {
|
|
65
|
-
millisecond: 1,
|
|
66
|
-
second: 1000,
|
|
67
|
-
minute: 60_000,
|
|
68
|
-
hour: 3_600_000,
|
|
69
|
-
day: DAY_MS,
|
|
70
|
-
week: 7 * DAY_MS,
|
|
71
|
-
month: 30 * DAY_MS, // month ticks step by calendar months; this is the sizing estimate
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Auto-tick candidates: (stepMs, defaultFormat) pairs from minutes to years.
|
|
75
|
-
const AUTO_TICKS: Array<{ unit: GanttTickUnit; count: number; format: string }> = [
|
|
76
|
-
{ unit: 'minute', count: 1, format: '%H:%M' },
|
|
77
|
-
{ unit: 'minute', count: 15, format: '%H:%M' },
|
|
78
|
-
{ unit: 'hour', count: 1, format: '%H:%M' },
|
|
79
|
-
{ unit: 'hour', count: 6, format: '%H:%M' },
|
|
80
|
-
{ unit: 'day', count: 1, format: '%m-%d' },
|
|
81
|
-
{ unit: 'week', count: 1, format: '%m-%d' },
|
|
82
|
-
{ unit: 'week', count: 2, format: '%m-%d' },
|
|
83
|
-
{ unit: 'month', count: 1, format: '%b %Y' },
|
|
84
|
-
{ unit: 'month', count: 3, format: '%b %Y' },
|
|
85
|
-
{ unit: 'month', count: 12, format: '%Y' },
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
interface TickPlan {
|
|
89
|
-
unit: GanttTickUnit
|
|
90
|
-
count: number
|
|
91
|
-
format: string
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const INLINE_FORMAT_TAG = /<\/?(?:b|strong|i|em|u|s|del)\s*>/gi
|
|
95
|
-
|
|
96
|
-
export function resolveGanttRenderStyle(options: RenderOptions = {}): ResolvedRenderStyle {
|
|
97
|
-
return resolveRenderStyle(options, GANTT_STYLE_DEFAULTS)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function ganttTitleFontSize(style: ResolvedRenderStyle): number {
|
|
101
|
-
return Math.max(17, style.groupHeaderFontSize)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function ganttTitleY(style: ResolvedRenderStyle): number {
|
|
105
|
-
const titleHeight = ganttTitleHeight(style)
|
|
106
|
-
return titleHeight === GL.titleHeight ? 18 : titleHeight / 2
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function ganttAxisLabelOffset(style: ResolvedRenderStyle): number {
|
|
110
|
-
return Math.max(10, style.edgeLabelFontSize * 0.75)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function ganttMeasureTextWidth(
|
|
114
|
-
text: string,
|
|
115
|
-
fontSize: number,
|
|
116
|
-
fontWeight: number,
|
|
117
|
-
letterSpacing = 0,
|
|
118
|
-
): number {
|
|
119
|
-
const plain = text.replace(INLINE_FORMAT_TAG, '')
|
|
120
|
-
const codepoints = [...plain].length
|
|
121
|
-
const tracking = Math.max(0, codepoints - 1) * letterSpacing
|
|
122
|
-
return Math.max(0, estimateTextWidth(plain, fontSize, fontWeight) + tracking)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function ganttTitleHeight(style: ResolvedRenderStyle): number {
|
|
126
|
-
return Math.max(GL.titleHeight, Math.ceil(ganttTitleFontSize(style) * 1.3) + 8)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function ganttAxisHeight(style: ResolvedRenderStyle): number {
|
|
130
|
-
return Math.max(GL.axisHeight, Math.ceil(ganttAxisLabelOffset(style) + style.edgeLabelFontSize * 0.65 + 4))
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function ganttRowHeight(style: ResolvedRenderStyle, barHeight: number): number {
|
|
134
|
-
const labelLineHeight = Math.max(style.nodeLabelFontSize, style.groupHeaderFontSize) * 1.3
|
|
135
|
-
return Math.ceil(Math.max(barHeight, labelLineHeight)) + GL.rowGap
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Pick the tick plan: the explicit `tickInterval` when it stays under the
|
|
140
|
-
* GANTT_MAX_TICKS bound (mermaid PR #7197 regression: tiny intervals must not
|
|
141
|
-
* generate unbounded ticks), otherwise the smallest auto candidate that fits.
|
|
142
|
-
*/
|
|
143
|
-
export function planTicks(schedule: GanttSchedule, model: GanttModel, targetTicks = 8): TickPlan {
|
|
144
|
-
const span = schedule.timeMax - schedule.timeMin
|
|
145
|
-
if (model.tickInterval) {
|
|
146
|
-
const step = TICK_UNIT_MS[model.tickInterval.unit] * model.tickInterval.count
|
|
147
|
-
if (span / step <= GANTT_MAX_TICKS) {
|
|
148
|
-
return { ...model.tickInterval, format: model.axisFormat ?? defaultFormatFor(model.tickInterval.unit) }
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
for (const cand of AUTO_TICKS) {
|
|
152
|
-
const step = TICK_UNIT_MS[cand.unit] * cand.count
|
|
153
|
-
if (span / step <= targetTicks) {
|
|
154
|
-
return { unit: cand.unit, count: cand.count, format: model.axisFormat ?? cand.format }
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const last = AUTO_TICKS[AUTO_TICKS.length - 1]!
|
|
158
|
-
// Beyond the largest candidate: scale year ticks up until bounded.
|
|
159
|
-
let count = last.count
|
|
160
|
-
while ((span / (TICK_UNIT_MS.month * count)) > GANTT_MAX_TICKS) count *= 2
|
|
161
|
-
return { unit: 'month', count, format: model.axisFormat ?? last.format }
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function defaultFormatFor(unit: GanttTickUnit): string {
|
|
165
|
-
switch (unit) {
|
|
166
|
-
case 'millisecond': case 'second': return '%H:%M:%S'
|
|
167
|
-
case 'minute': case 'hour': return '%H:%M'
|
|
168
|
-
case 'day': case 'week': return '%m-%d'
|
|
169
|
-
case 'month': return '%b %Y'
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** First tick instant at or before timeMin, aligned to the unit (weeks align
|
|
174
|
-
* to the model's weekStart; months to the 1st; days to midnight UTC). */
|
|
175
|
-
function alignTickStart(timeMin: EpochMs, plan: TickPlan, weekStart: number): EpochMs {
|
|
176
|
-
if (plan.unit === 'week') {
|
|
177
|
-
let t = startOfDay(timeMin)
|
|
178
|
-
let steps = 0
|
|
179
|
-
while (dayOfWeek(t) !== weekStart && steps++ < 7) t -= DAY_MS
|
|
180
|
-
return t
|
|
181
|
-
}
|
|
182
|
-
if (plan.unit === 'month') {
|
|
183
|
-
const d = new Date(timeMin)
|
|
184
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)
|
|
185
|
-
}
|
|
186
|
-
if (plan.unit === 'day') return startOfDay(timeMin)
|
|
187
|
-
const step = TICK_UNIT_MS[plan.unit] * plan.count
|
|
188
|
-
return Math.floor(timeMin / step) * step
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function nextTick(t: EpochMs, plan: TickPlan): EpochMs {
|
|
192
|
-
if (plan.unit === 'month') {
|
|
193
|
-
const d = new Date(t)
|
|
194
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + plan.count, 1)
|
|
195
|
-
}
|
|
196
|
-
return t + TICK_UNIT_MS[plan.unit] * plan.count
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Resolve the tick instants for a schedule (shared by SVG and ASCII).
|
|
201
|
-
* Bounded by GANTT_MAX_TICKS regardless of inputs.
|
|
202
|
-
*/
|
|
203
|
-
export function resolveTicks(schedule: GanttSchedule, model: GanttModel, targetTicks = 8): Array<{ time: EpochMs; label: string }> {
|
|
204
|
-
const plan = planTicks(schedule, model, targetTicks)
|
|
205
|
-
const weekStart = WEEKDAY_INDEX[model.weekStart]
|
|
206
|
-
const out: Array<{ time: EpochMs; label: string }> = []
|
|
207
|
-
let t = alignTickStart(schedule.timeMin, plan, weekStart)
|
|
208
|
-
let guard = 0
|
|
209
|
-
while (t <= schedule.timeMax && guard++ <= GANTT_MAX_TICKS) {
|
|
210
|
-
if (t >= schedule.timeMin) out.push({ time: t, label: formatGanttInstant(t, plan.format) })
|
|
211
|
-
t = nextTick(t, plan)
|
|
212
|
-
}
|
|
213
|
-
// A coarse explicit interval over a short span (e.g. `tickInterval 1month`
|
|
214
|
-
// on a 2-day chart) can leave zero in-range ticks; an axis must never be
|
|
215
|
-
// empty, so fall back to a single tick at the range start.
|
|
216
|
-
if (out.length === 0) {
|
|
217
|
-
out.push({ time: schedule.timeMin, label: formatGanttInstant(schedule.timeMin, plan.format) })
|
|
218
|
-
}
|
|
219
|
-
return out
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Compact-mode lane packing: within one section, tasks (source order) go to
|
|
224
|
-
* the first lane whose latest end is <= the task's start. Deterministic and
|
|
225
|
-
* overlap-free by construction.
|
|
226
|
-
*/
|
|
227
|
-
export function packCompactLanes(tasks: Array<{ start: EpochMs; end: EpochMs }>): number[] {
|
|
228
|
-
const laneEnds: EpochMs[] = []
|
|
229
|
-
const laneOf: number[] = []
|
|
230
|
-
for (const t of tasks) {
|
|
231
|
-
let lane = laneEnds.findIndex(end => end <= t.start)
|
|
232
|
-
if (lane === -1) {
|
|
233
|
-
lane = laneEnds.length
|
|
234
|
-
laneEnds.push(t.end)
|
|
235
|
-
} else {
|
|
236
|
-
laneEnds[lane] = t.end
|
|
237
|
-
}
|
|
238
|
-
laneOf.push(lane)
|
|
239
|
-
}
|
|
240
|
-
return laneOf
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function layoutGantt(model: GanttModel, schedule: GanttSchedule, options: GanttLayoutOptions = {}): GanttLayoutResult {
|
|
244
|
-
const style = resolveGanttRenderStyle(options.renderOptions)
|
|
245
|
-
const compact = options.compact ?? (model.displayMode === 'compact')
|
|
246
|
-
const barHeight = options.barHeight ?? model.barHeight ?? GL.barHeight
|
|
247
|
-
const rowH = ganttRowHeight(style, barHeight)
|
|
248
|
-
|
|
249
|
-
const vertTasks = schedule.tasks.filter(t => t.tags.includes('vert'))
|
|
250
|
-
const rowTasks = schedule.tasks.filter(t => !t.tags.includes('vert'))
|
|
251
|
-
|
|
252
|
-
// ---- label column ---------------------------------------------------------
|
|
253
|
-
let labelColumnWidth = 0
|
|
254
|
-
for (const t of rowTasks) {
|
|
255
|
-
const label = applyTextTransform(t.label, style.nodeTextTransform)
|
|
256
|
-
labelColumnWidth = Math.max(labelColumnWidth, ganttMeasureTextWidth(label, style.nodeLabelFontSize, style.nodeLabelFontWeight, style.nodeLetterSpacing))
|
|
257
|
-
}
|
|
258
|
-
for (const s of model.sections) {
|
|
259
|
-
if (s.label) {
|
|
260
|
-
const label = applyTextTransform(s.label, style.groupTextTransform)
|
|
261
|
-
labelColumnWidth = Math.max(labelColumnWidth, ganttMeasureTextWidth(label, style.groupHeaderFontSize, style.groupHeaderFontWeight, style.groupLetterSpacing))
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
labelColumnWidth = Math.ceil(labelColumnWidth) + GL.labelGap
|
|
265
|
-
|
|
266
|
-
const width = options.width ?? (GL.padding * 2 + labelColumnWidth + GL.plotWidth)
|
|
267
|
-
const plotX = GL.padding + labelColumnWidth
|
|
268
|
-
const plotW = Math.max(120, width - plotX - GL.padding)
|
|
269
|
-
|
|
270
|
-
const titleH = model.title ? ganttTitleHeight(style) : 0
|
|
271
|
-
const axisH = ganttAxisHeight(style)
|
|
272
|
-
const topAxisH = model.topAxis ? axisH : 0
|
|
273
|
-
const plotY = GL.padding + titleH + topAxisH
|
|
274
|
-
|
|
275
|
-
const span = schedule.timeMax - schedule.timeMin
|
|
276
|
-
const xOf = (t: EpochMs): number => plotX + ((t - schedule.timeMin) / span) * plotW
|
|
277
|
-
|
|
278
|
-
// ---- rows + bars (vert tasks never consume a row) --------------------------
|
|
279
|
-
const bars: GanttBarLayout[] = []
|
|
280
|
-
const rows: GanttRowLayout[] = []
|
|
281
|
-
const sections: GanttSectionBand[] = []
|
|
282
|
-
let y = plotY
|
|
283
|
-
|
|
284
|
-
for (let si = 0; si < model.sections.length; si++) {
|
|
285
|
-
const section = model.sections[si]!
|
|
286
|
-
const sectionTasks = rowTasks.filter(t => t.sectionIndex === si)
|
|
287
|
-
if (sectionTasks.length === 0 && section.label === undefined) continue
|
|
288
|
-
// Bars/rows reference the BAND index in the emitted sections array (empty
|
|
289
|
-
// implicit sections are skipped, so it can differ from the model index).
|
|
290
|
-
const bandIndex = sections.length
|
|
291
|
-
const bandStartY = y
|
|
292
|
-
const rowStart = rows.length
|
|
293
|
-
if (section.label !== undefined) y += rowH // the section header row
|
|
294
|
-
|
|
295
|
-
const lanes = compact ? packCompactLanes(sectionTasks) : sectionTasks.map((_, i) => i)
|
|
296
|
-
const laneCount = sectionTasks.length === 0 ? 0 : Math.max(...lanes) + 1
|
|
297
|
-
const laneRows: GanttRowLayout[] = []
|
|
298
|
-
for (let li = 0; li < laneCount; li++) {
|
|
299
|
-
laneRows.push({ barIndexes: [], sectionIndex: bandIndex, y: y + li * rowH, h: barHeight })
|
|
300
|
-
}
|
|
301
|
-
sectionTasks.forEach((t, i) => {
|
|
302
|
-
const lane = lanes[i]!
|
|
303
|
-
const row = laneRows[lane]!
|
|
304
|
-
const x = xOf(t.start)
|
|
305
|
-
const w = Math.max(t.end > t.start ? 2 : 0, xOf(t.end) - x)
|
|
306
|
-
const isMilestone = t.tags.includes('milestone')
|
|
307
|
-
// Milestone diamonds extend ±barHeight/2 around their center; clamp the
|
|
308
|
-
// center so a milestone at the range edge stays inside the plot band
|
|
309
|
-
// (the ASCII renderer clamps its grid column the same way — issue #26:
|
|
310
|
-
// shared geometry, not per-renderer patch-ups).
|
|
311
|
-
let milestoneX: number | undefined
|
|
312
|
-
if (isMilestone) {
|
|
313
|
-
const r = barHeight / 2
|
|
314
|
-
const lo = plotX + r
|
|
315
|
-
const hi = Math.max(lo, plotX + plotW - r)
|
|
316
|
-
milestoneX = Math.min(hi, Math.max(lo, x + w / 2))
|
|
317
|
-
}
|
|
318
|
-
bars.push({
|
|
319
|
-
taskIndex: t.index, id: t.id, label: t.label, tags: t.tags, sectionIndex: bandIndex,
|
|
320
|
-
x, y: row.y, w, h: barHeight,
|
|
321
|
-
milestoneX,
|
|
322
|
-
rowIndex: rowStart + (section.label !== undefined ? 1 : 0) + lane,
|
|
323
|
-
start: t.start, end: t.end,
|
|
324
|
-
})
|
|
325
|
-
row.barIndexes.push(bars.length - 1)
|
|
326
|
-
})
|
|
327
|
-
rows.push(...laneRows)
|
|
328
|
-
y += laneCount * rowH
|
|
329
|
-
sections.push({
|
|
330
|
-
label: section.label, y: bandStartY, h: y - bandStartY,
|
|
331
|
-
rowStart, rowEnd: rows.length,
|
|
332
|
-
})
|
|
333
|
-
y += GL.sectionGap
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const plotH = Math.max(rowH, y - plotY)
|
|
337
|
-
const height = plotY + plotH + axisH + GL.padding
|
|
338
|
-
|
|
339
|
-
// ---- ticks / markers --------------------------------------------------------
|
|
340
|
-
const ticks: GanttTick[] = resolveTicks(schedule, model).map(t => ({
|
|
341
|
-
time: t.time, x: xOf(t.time), label: t.label,
|
|
342
|
-
}))
|
|
343
|
-
|
|
344
|
-
const verts: GanttVertLayout[] = vertTasks.map(t => ({
|
|
345
|
-
taskIndex: t.index, label: t.label,
|
|
346
|
-
x: xOf(t.start + (t.end - t.start) / 2), time: t.start,
|
|
347
|
-
}))
|
|
348
|
-
|
|
349
|
-
const todayX = options.today !== undefined && options.today >= schedule.timeMin && options.today <= schedule.timeMax
|
|
350
|
-
? xOf(options.today)
|
|
351
|
-
: undefined
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
title: model.title,
|
|
355
|
-
width, height,
|
|
356
|
-
plot: { x: plotX, y: plotY, w: plotW, h: plotH },
|
|
357
|
-
labelColumnWidth,
|
|
358
|
-
rows, sections, bars, verts, ticks,
|
|
359
|
-
topAxis: model.topAxis,
|
|
360
|
-
todayX,
|
|
361
|
-
timeMin: schedule.timeMin, timeMax: schedule.timeMax,
|
|
362
|
-
dateOnly: schedule.dateOnly,
|
|
363
|
-
compact, barHeight,
|
|
364
|
-
}
|
|
365
|
-
}
|