dreamcontext 0.17.1 → 0.18.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.
- package/README.md +321 -565
- package/agents/sleep-product.md +21 -2
- package/agents/sleep-state.md +24 -0
- package/agents/sleep-tasks.md +16 -0
- package/dist/agents/sleep-product.md +21 -2
- package/dist/agents/sleep-state.md +24 -0
- package/dist/agents/sleep-tasks.md +16 -0
- package/dist/dashboard/announcements/dashboard-highlights-0-17-0-18.excalidraw.md +1531 -0
- package/dist/dashboard/announcements/goal-skill-v2.excalidraw.md +1490 -0
- package/dist/dashboard/announcements/task-manager.excalidraw.md +1217 -0
- package/dist/dashboard/announcements/visual-announcements.excalidraw.md +1373 -0
- package/dist/dashboard/announcements.json +38 -0
- package/dist/dashboard/assets/{BrainCanvas3D-DyF_3yYD.js → BrainCanvas3D-D9G3dOLf.js} +1 -1
- package/dist/dashboard/assets/{_baseUniq-Do8VMBA0.js → _baseUniq-Cyshlz4Y.js} +1 -1
- package/dist/dashboard/assets/{ar-SA-G6X2FPQ2-DmbXDb2R.js → ar-SA-G6X2FPQ2-qj-2Cbgo.js} +1 -1
- package/dist/dashboard/assets/{arc-CwtUBQfU.js → arc-0OnX5WDs.js} +1 -1
- package/dist/dashboard/assets/{architectureDiagram-Q4EWVU46-O9bOog_f.js → architectureDiagram-Q4EWVU46-Cx3c0nUi.js} +1 -1
- package/dist/dashboard/assets/{az-AZ-76LH7QW2-c9Zk10vG.js → az-AZ-76LH7QW2-CBuoh6M3.js} +1 -1
- package/dist/dashboard/assets/{bg-BG-XCXSNQG7-uMTg84lX.js → bg-BG-XCXSNQG7-X5QYyZWx.js} +1 -1
- package/dist/dashboard/assets/{blockDiagram-DXYQGD6D-BTENXCSO.js → blockDiagram-DXYQGD6D-BwESAg1j.js} +1 -1
- package/dist/dashboard/assets/{bn-BD-2XOGV67Q-DUFKHcua.js → bn-BD-2XOGV67Q-DlodQLNR.js} +1 -1
- package/dist/dashboard/assets/{c4Diagram-AHTNJAMY-DMXPWRiQ.js → c4Diagram-AHTNJAMY-CopL0lbP.js} +1 -1
- package/dist/dashboard/assets/{ca-ES-6MX7JW3Y-BuYX1q89.js → ca-ES-6MX7JW3Y-DfqF6Yhy.js} +1 -1
- package/dist/dashboard/assets/channel-BLisRbYb.js +1 -0
- package/dist/dashboard/assets/{chunk-4BX2VUAB-DgefvnWS.js → chunk-4BX2VUAB-CRwifLK3.js} +1 -1
- package/dist/dashboard/assets/{chunk-4TB4RGXK-BnFO5G1t.js → chunk-4TB4RGXK-uxJYY_64.js} +1 -1
- package/dist/dashboard/assets/{chunk-55IACEB6-COm2TYEM.js → chunk-55IACEB6-DhYIp7Oc.js} +1 -1
- package/dist/dashboard/assets/{chunk-EDXVE4YY-CtsGCwZp.js → chunk-EDXVE4YY-CCxfcirt.js} +1 -1
- package/dist/dashboard/assets/{chunk-FMBD7UC4-cfSvx35j.js → chunk-FMBD7UC4-D7OC8QFC.js} +1 -1
- package/dist/dashboard/assets/{chunk-OYMX7WX6-DAhDKteL.js → chunk-OYMX7WX6-CwHgaUQo.js} +1 -1
- package/dist/dashboard/assets/{chunk-QZHKN3VN-B5h4qML3.js → chunk-QZHKN3VN-7Idpf6YJ.js} +1 -1
- package/dist/dashboard/assets/{chunk-YZCP3GAM-CGp_NiRg.js → chunk-YZCP3GAM-D4Lh0fgr.js} +1 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-CgqeQiHi.js +1 -0
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-CgqeQiHi.js +1 -0
- package/dist/dashboard/assets/clone-CQXNMCV5.js +1 -0
- package/dist/dashboard/assets/{cose-bilkent-S5V4N54A-Dk7CMFA4.js → cose-bilkent-S5V4N54A-BYcMtJTF.js} +1 -1
- package/dist/dashboard/assets/{cs-CZ-2BRQDIVT-zfUTiS_d.js → cs-CZ-2BRQDIVT-rnrpKdSJ.js} +1 -1
- package/dist/dashboard/assets/{da-DK-5WZEPLOC-CU14f8NA.js → da-DK-5WZEPLOC-D5OGAvk7.js} +1 -1
- package/dist/dashboard/assets/{dagre-KV5264BT-BiMVxC4Q.js → dagre-KV5264BT-V0f1_b4R.js} +1 -1
- package/dist/dashboard/assets/{de-DE-XR44H4JA-CDOHAJGo.js → de-DE-XR44H4JA-CDyb8YfL.js} +1 -1
- package/dist/dashboard/assets/{diagram-5BDNPKRD-DfJEsVTA.js → diagram-5BDNPKRD-BmpizoaS.js} +1 -1
- package/dist/dashboard/assets/{diagram-G4DWMVQ6-CztLHIcY.js → diagram-G4DWMVQ6-ClQg-LTu.js} +1 -1
- package/dist/dashboard/assets/{diagram-MMDJMWI5-DqoQLlWK.js → diagram-MMDJMWI5-BkXcDMIV.js} +1 -1
- package/dist/dashboard/assets/{diagram-TYMM5635-DvyvQBCc.js → diagram-TYMM5635-BbFiiCM2.js} +1 -1
- package/dist/dashboard/assets/{el-GR-BZB4AONW-ChUphbcv.js → el-GR-BZB4AONW-Y1YnKZL0.js} +1 -1
- package/dist/dashboard/assets/{erDiagram-SMLLAGMA-D_uSs2_2.js → erDiagram-SMLLAGMA-Dzdv7_l5.js} +1 -1
- package/dist/dashboard/assets/{es-ES-U4NZUMDT-BNalBEhb.js → es-ES-U4NZUMDT-D0T536hs.js} +1 -1
- package/dist/dashboard/assets/{eu-ES-A7QVB2H4-BMiQyA2y.js → eu-ES-A7QVB2H4-Bfrya0et.js} +1 -1
- package/dist/dashboard/assets/{fa-IR-HGAKTJCU-Bd6ZnTSo.js → fa-IR-HGAKTJCU-pYE_hG-L.js} +1 -1
- package/dist/dashboard/assets/{fi-FI-Z5N7JZ37-BWAfJadC.js → fi-FI-Z5N7JZ37-D3C-fNyk.js} +1 -1
- package/dist/dashboard/assets/{flowDiagram-DWJPFMVM-Bmsp6kyU.js → flowDiagram-DWJPFMVM-CFhyjwKY.js} +1 -1
- package/dist/dashboard/assets/{fr-FR-RHASNOE6-CspbYzOW.js → fr-FR-RHASNOE6-CgwnG5JW.js} +1 -1
- package/dist/dashboard/assets/{ganttDiagram-T4ZO3ILL-wEdysXo_.js → ganttDiagram-T4ZO3ILL-BRKRiSzf.js} +1 -1
- package/dist/dashboard/assets/{gitGraphDiagram-UUTBAWPF-BEiGpPBj.js → gitGraphDiagram-UUTBAWPF-CTqCK49d.js} +1 -1
- package/dist/dashboard/assets/{gl-ES-HMX3MZ6V-CV76vsWr.js → gl-ES-HMX3MZ6V-DjJTqTm3.js} +1 -1
- package/dist/dashboard/assets/{graph-CZFIeNHZ.js → graph-D429kSbY.js} +1 -1
- package/dist/dashboard/assets/{he-IL-6SHJWFNN-Y1VoXJ_H.js → he-IL-6SHJWFNN-C84FlH6r.js} +1 -1
- package/dist/dashboard/assets/{hi-IN-IWLTKZ5I-Crh5S49o.js → hi-IN-IWLTKZ5I-Blhkfum2.js} +1 -1
- package/dist/dashboard/assets/{hu-HU-A5ZG7DT2-D4I3gCbp.js → hu-HU-A5ZG7DT2-DLC1JfN-.js} +1 -1
- package/dist/dashboard/assets/{id-ID-SAP4L64H-Chvzkuvi.js → id-ID-SAP4L64H-C3pB_IWB.js} +1 -1
- package/dist/dashboard/assets/image-FgR93jdt.js +1 -0
- package/dist/dashboard/assets/index-2m8ueOUn.js +1 -0
- package/dist/dashboard/assets/index-CWwjuihq.css +32 -0
- package/dist/dashboard/assets/{index-C7Bo5AQH.js → index-CbOXCDms.js} +1 -1
- package/dist/dashboard/assets/index-SJ64pf-4.js +551 -0
- package/dist/dashboard/assets/{infoDiagram-42DDH7IO-BzfuDHl4.js → infoDiagram-42DDH7IO-CIzDShDw.js} +1 -1
- package/dist/dashboard/assets/{ishikawaDiagram-UXIWVN3A-BVoNJ9VS.js → ishikawaDiagram-UXIWVN3A-CuasYzdX.js} +1 -1
- package/dist/dashboard/assets/{it-IT-JPQ66NNP-BH_gN5es.js → it-IT-JPQ66NNP-DGGEoNPu.js} +1 -1
- package/dist/dashboard/assets/{ja-JP-DBVTYXUO-DU_WmLVa.js → ja-JP-DBVTYXUO-CEqP9aps.js} +1 -1
- package/dist/dashboard/assets/{journeyDiagram-VCZTEJTY-DbwICa_a.js → journeyDiagram-VCZTEJTY-DHiq2OTQ.js} +1 -1
- package/dist/dashboard/assets/{kaa-6HZHGXH3-KYU9qowM.js → kaa-6HZHGXH3-GOFmTAXq.js} +1 -1
- package/dist/dashboard/assets/{kab-KAB-ZGHBKWFO-bjhyiUq5.js → kab-KAB-ZGHBKWFO-B865Wwzu.js} +1 -1
- package/dist/dashboard/assets/{kanban-definition-6JOO6SKY-D9XucLs4.js → kanban-definition-6JOO6SKY-BhlTKFbL.js} +1 -1
- package/dist/dashboard/assets/{kk-KZ-P5N5QNE5-CYTx_dAZ.js → kk-KZ-P5N5QNE5-CNfuE6b6.js} +1 -1
- package/dist/dashboard/assets/{km-KH-HSX4SM5Z-DqsuY4Lf.js → km-KH-HSX4SM5Z-CsmgRWxu.js} +1 -1
- package/dist/dashboard/assets/{ko-KR-MTYHY66A-BZe7NywF.js → ko-KR-MTYHY66A-B_02RgEz.js} +1 -1
- package/dist/dashboard/assets/{ku-TR-6OUDTVRD-F5d6HFWt.js → ku-TR-6OUDTVRD-JfQA5u05.js} +1 -1
- package/dist/dashboard/assets/{layout-CotqU0S9.js → layout-DvrQSvOI.js} +1 -1
- package/dist/dashboard/assets/{linear-Dqv87Scf.js → linear-6r0qttLs.js} +1 -1
- package/dist/dashboard/assets/{lt-LT-XHIRWOB4-BCCuaPbS.js → lt-LT-XHIRWOB4-DWFUXEdf.js} +1 -1
- package/dist/dashboard/assets/{lv-LV-5QDEKY6T-NLGi-vJ6.js → lv-LV-5QDEKY6T-C5yAd0n_.js} +1 -1
- package/dist/dashboard/assets/{min-BbJdnc3h.js → min-D_EP9dBf.js} +1 -1
- package/dist/dashboard/assets/{mindmap-definition-QFDTVHPH-Dk4QySu7.js → mindmap-definition-QFDTVHPH-Col3ao9B.js} +1 -1
- package/dist/dashboard/assets/{mr-IN-CRQNXWMA-BnGDIgVN.js → mr-IN-CRQNXWMA-Dwjz0Xdm.js} +1 -1
- package/dist/dashboard/assets/{my-MM-5M5IBNSE-CspgYE9_.js → my-MM-5M5IBNSE-EXJDNyjA.js} +1 -1
- package/dist/dashboard/assets/{nb-NO-T6EIAALU-BeRPw3hu.js → nb-NO-T6EIAALU-BWm2bgLd.js} +1 -1
- package/dist/dashboard/assets/{nl-NL-IS3SIHDZ-C-G-bljM.js → nl-NL-IS3SIHDZ-f8nP-yp-.js} +1 -1
- package/dist/dashboard/assets/{nn-NO-6E72VCQL-Ct7VZY8D.js → nn-NO-6E72VCQL-B0c_gCNR.js} +1 -1
- package/dist/dashboard/assets/{oc-FR-POXYY2M6-Cv5-C4Qq.js → oc-FR-POXYY2M6-C40PSwAh.js} +1 -1
- package/dist/dashboard/assets/{pa-IN-N4M65BXN-DAgkIThL.js → pa-IN-N4M65BXN-DDcgXFkB.js} +1 -1
- package/dist/dashboard/assets/{percentages-BXMCSKIN-vidRYabK.js → percentages-BXMCSKIN-MHBQP8nI.js} +7 -7
- package/dist/dashboard/assets/{pica-Cy-Xl-mi.js → pica-C5CFA09W.js} +1 -1
- package/dist/dashboard/assets/{pieDiagram-DEJITSTG-BnP4-zwd.js → pieDiagram-DEJITSTG-DFHmB0fL.js} +1 -1
- package/dist/dashboard/assets/{pl-PL-T2D74RX3-BuJQ3HD-.js → pl-PL-T2D74RX3-yFTBt0Xu.js} +1 -1
- package/dist/dashboard/assets/{pt-BR-5N22H2LF-BbAqsvD6.js → pt-BR-5N22H2LF-ilAW3Fdv.js} +1 -1
- package/dist/dashboard/assets/{pt-PT-UZXXM6DQ-DzFJedU3.js → pt-PT-UZXXM6DQ-CXHFN95K.js} +1 -1
- package/dist/dashboard/assets/{quadrantDiagram-34T5L4WZ-BXN88cHy.js → quadrantDiagram-34T5L4WZ-CR732_oP.js} +1 -1
- package/dist/dashboard/assets/{requirementDiagram-MS252O5E-D34hL42a.js → requirementDiagram-MS252O5E-mKoVG52Z.js} +1 -1
- package/dist/dashboard/assets/{ro-RO-JPDTUUEW-BV2-sOiv.js → ro-RO-JPDTUUEW-BKlWpyF4.js} +1 -1
- package/dist/dashboard/assets/{ru-RU-B4JR7IUQ-BCL4N9Ej.js → ru-RU-B4JR7IUQ-BGoxlhJm.js} +1 -1
- package/dist/dashboard/assets/{sankeyDiagram-XADWPNL6-0mFeok-3.js → sankeyDiagram-XADWPNL6-DXipts7M.js} +1 -1
- package/dist/dashboard/assets/{sequenceDiagram-FGHM5R23-C-5nW5j6.js → sequenceDiagram-FGHM5R23-DFQhU8q7.js} +1 -1
- package/dist/dashboard/assets/{si-LK-N5RQ5JYF-CNhaw4jx.js → si-LK-N5RQ5JYF-yDbJWFTH.js} +1 -1
- package/dist/dashboard/assets/{sk-SK-C5VTKIMK-mHCphOXu.js → sk-SK-C5VTKIMK-DglyhbNB.js} +1 -1
- package/dist/dashboard/assets/{sl-SI-NN7IZMDC--lzgHthQ.js → sl-SI-NN7IZMDC-DPfq0s4I.js} +1 -1
- package/dist/dashboard/assets/{stateDiagram-FHFEXIEX-C50iDFqe.js → stateDiagram-FHFEXIEX-Dm50jiEh.js} +1 -1
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CoSm11sD.js +1 -0
- package/dist/dashboard/assets/{subset-shared.chunk-DNsjL37s.js → subset-shared.chunk-OHz6M6ct.js} +1 -1
- package/dist/dashboard/assets/{subset-worker.chunk-BaV3r-bl.js → subset-worker.chunk-BzwrOBtO.js} +1 -1
- package/dist/dashboard/assets/{sv-SE-XGPEYMSR-ckw8jfGN.js → sv-SE-XGPEYMSR-BLHNwr4k.js} +1 -1
- package/dist/dashboard/assets/{ta-IN-2NMHFXQM-CSeNmVhS.js → ta-IN-2NMHFXQM-Dw-6hUpN.js} +1 -1
- package/dist/dashboard/assets/{th-TH-HPSO5L25-Cvn1sg_3.js → th-TH-HPSO5L25-DPkcM_k9.js} +1 -1
- package/dist/dashboard/assets/{timeline-definition-GMOUNBTQ-DRYfuqHT.js → timeline-definition-GMOUNBTQ-BKFNQ_7e.js} +1 -1
- package/dist/dashboard/assets/{tr-TR-DEFEU3FU-CyhY22TB.js → tr-TR-DEFEU3FU-rBVsY5RS.js} +1 -1
- package/dist/dashboard/assets/{uk-UA-QMV73CPH-BvvAEO6U.js → uk-UA-QMV73CPH-CV6_yTZs.js} +1 -1
- package/dist/dashboard/assets/{vennDiagram-DHZGUBPP-Crril7Cj.js → vennDiagram-DHZGUBPP-BZb_r5tY.js} +1 -1
- package/dist/dashboard/assets/{vi-VN-M7AON7JQ-c7AwSUZ8.js → vi-VN-M7AON7JQ-CJMgSsLz.js} +1 -1
- package/dist/dashboard/assets/{wardley-RL74JXVD-Da5AhSWU.js → wardley-RL74JXVD-DgqjmWyN.js} +1 -1
- package/dist/dashboard/assets/{wardleyDiagram-NUSXRM2D-C4GeB_Df.js → wardleyDiagram-NUSXRM2D-BDpniS9m.js} +1 -1
- package/dist/dashboard/assets/webviewWindow-Bwv2421L.js +1 -0
- package/dist/dashboard/assets/window-BObcHN8e.js +1 -0
- package/dist/dashboard/assets/{xychartDiagram-5P7HB3ND-BPCFKXqR.js → xychartDiagram-5P7HB3ND-CCyPcx2A.js} +1 -1
- package/dist/dashboard/assets/{zh-CN-LNUGB5OW-BvNiZwKU.js → zh-CN-LNUGB5OW-9LJLF_AC.js} +1 -1
- package/dist/dashboard/assets/{zh-HK-E62DVLB3-CCFtoCWb.js → zh-HK-E62DVLB3-IefAiePp.js} +1 -1
- package/dist/dashboard/assets/{zh-TW-RAJ6MFWO-bYBr-stu.js → zh-TW-RAJ6MFWO-CHeY9rNZ.js} +1 -1
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +4099 -1538
- package/dist/skill-packs/agents/goal-implementer.md +42 -1
- package/dist/skill-packs/agents/goal-plan-reviewer.md +7 -0
- package/dist/skill-packs/agents/goal-planner.md +34 -0
- package/dist/skill-packs/catalog.json +31 -21
- package/dist/skill-packs/excalidraw/SKILL.md +244 -13
- package/dist/skill-packs/excalidraw/examples/Chart Kit.excalidraw.md +15740 -0
- package/dist/skill-packs/excalidraw/examples/Wireframe Kit.excalidraw.md +16860 -0
- package/dist/skill-packs/excalidraw/examples/atomic_check.js +99 -0
- package/dist/skill-packs/excalidraw/examples/chart.spec.json +122 -0
- package/dist/skill-packs/excalidraw/examples/chart_board.js +173 -0
- package/dist/skill-packs/excalidraw/examples/hello.spec.json +79 -9
- package/dist/skill-packs/excalidraw/examples/visual_board.js +82 -0
- package/dist/skill-packs/excalidraw/examples/wireframe_board.js +161 -0
- package/dist/skill-packs/excalidraw/scripts/build_excalidraw.js +292 -27
- package/dist/skill-packs/excalidraw/scripts/lib/charts.js +771 -0
- package/dist/skill-packs/excalidraw/scripts/lib/style.js +369 -35
- package/dist/skill-packs/excalidraw/scripts/lib/wireframe.js +406 -0
- package/dist/skill-packs/goal-skill/SKILL.md +369 -100
- package/dist/skill-packs/goal-skill/assets/goal-skill-demo.cjs +51 -0
- package/dist/skill-packs/goal-skill/assets/goal-skill-viewer.cjs +181 -0
- package/package.json +2 -1
- package/skill/references/integrations.md +54 -0
- package/skill/references/knowledge-and-recall.md +3 -1
- package/skill/references/sleep.md +4 -4
- package/skill-packs/agents/goal-implementer.md +42 -1
- package/skill-packs/agents/goal-plan-reviewer.md +7 -0
- package/skill-packs/agents/goal-planner.md +34 -0
- package/skill-packs/catalog.json +31 -21
- package/skill-packs/excalidraw/SKILL.md +244 -13
- package/skill-packs/excalidraw/examples/Chart Kit.excalidraw.md +15740 -0
- package/skill-packs/excalidraw/examples/Wireframe Kit.excalidraw.md +16860 -0
- package/skill-packs/excalidraw/examples/atomic_check.js +99 -0
- package/skill-packs/excalidraw/examples/chart.spec.json +122 -0
- package/skill-packs/excalidraw/examples/chart_board.js +173 -0
- package/skill-packs/excalidraw/examples/hello.spec.json +79 -9
- package/skill-packs/excalidraw/examples/visual_board.js +82 -0
- package/skill-packs/excalidraw/examples/wireframe_board.js +161 -0
- package/skill-packs/excalidraw/scripts/build_excalidraw.js +292 -27
- package/skill-packs/excalidraw/scripts/lib/charts.js +771 -0
- package/skill-packs/excalidraw/scripts/lib/style.js +369 -35
- package/skill-packs/excalidraw/scripts/lib/wireframe.js +406 -0
- package/skill-packs/goal-skill/SKILL.md +369 -100
- package/skill-packs/goal-skill/assets/goal-skill-demo.cjs +51 -0
- package/skill-packs/goal-skill/assets/goal-skill-viewer.cjs +181 -0
- package/skill-task-manager/SKILL.md +93 -0
- package/dist/dashboard/assets/channel-2YfRjala.js +0 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-DB_UnN1h.js +0 -1
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-DB_UnN1h.js +0 -1
- package/dist/dashboard/assets/clone-DaDvB3N6.js +0 -1
- package/dist/dashboard/assets/index-BIfrbaFS.js +0 -516
- package/dist/dashboard/assets/index-BdZ3tppu.css +0 -32
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-eW9-s0Sm.js +0 -1
- package/dist/dashboard/assets/webviewWindow-BbG9Cr7f.js +0 -1
- package/dist/dashboard/assets/window-DmNpeJAL.js +0 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// atomic_check.js — the regression guard for the kit's core promise:
|
|
2
|
+
// every chart type is a plug-in adaptor, drivable from ONE spec element with DATA only.
|
|
3
|
+
//
|
|
4
|
+
// Run: node examples/atomic_check.js
|
|
5
|
+
// Each type below gets a single spec element and nothing else — no coordinates, no layout, no JS
|
|
6
|
+
// helpers. If it draws elements with a clean audit, it is genuinely atomic. If someone adds a chart
|
|
7
|
+
// to charts.js but forgets to register it in COMPOSITES, or breaks it on minimal input, this fails.
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const { buildExcalidraw } = require(path.resolve(__dirname, '../scripts/build_excalidraw.js'));
|
|
11
|
+
|
|
12
|
+
// Minimal-but-real input per type. Deliberately sparse: a chart must degrade sanely, not assume
|
|
13
|
+
// the author passed every option.
|
|
14
|
+
const CASES = {
|
|
15
|
+
lineChart: { type: 'lineChart', w: 400, h: 240, xLabels: ['1', '2', '3'], series: [{ label: 'DAU', points: [10, 30, 20] }] },
|
|
16
|
+
barChart: { type: 'barChart', w: 400, h: 240, bars: [{ label: 'US', value: 266 }, { label: 'TR', value: 22 }] },
|
|
17
|
+
barCompare: { type: 'barCompare', w: 400, h: 240, seriesLabels: ['W1', 'W2'], groups: [{ label: 'CPM', values: [139, 169] }] },
|
|
18
|
+
stackedBar: { type: 'stackedBar', w: 400, h: 240, seriesLabels: ['a', 'b'], groups: [{ label: 'X', values: [3, 7] }] },
|
|
19
|
+
gantt: { type: 'gantt', w: 600, tasks: [{ label: 'iş', start: '2026-07-16', end: '2026-07-20', done: 0.4 }] },
|
|
20
|
+
quadrant: { type: 'quadrant', w: 400, h: 400, items: [{ label: 'A', x: 0.8, y: 0.8 }, { label: 'B', x: 0.2, y: 0.3 }] },
|
|
21
|
+
donut: { type: 'donut', r: 80, slices: [{ label: 'a', value: 70 }, { label: 'b', value: 30 }] },
|
|
22
|
+
pie: { type: 'pie', r: 80, slices: [{ label: 'a', value: 60 }, { label: 'b', value: 40 }] },
|
|
23
|
+
sparkline: { type: 'sparkline', w: 160, h: 40, points: [5, 9, 4, 8] },
|
|
24
|
+
heatmap: { type: 'heatmap', rows: ['r1', 'r2'], cols: ['D0', 'D1'], values: [[100, 11], [100, 9]] },
|
|
25
|
+
table: { type: 'table', headers: ['Plan', 'Churn'], rows: [['Pro', '3.4%']] },
|
|
26
|
+
timeline: { type: 'timeline', w: 800, events: [{ label: 'başladı', at: '2026-07-03' }, { label: 'review', at: '2026-07-16' }] },
|
|
27
|
+
kpi: { type: 'kpi', w: 260, label: 'DAU', value: '32', delta: '−%57' },
|
|
28
|
+
callout: { type: 'callout', w: 600, title: 'not', text: 'metin hep ölçüde kalır.' },
|
|
29
|
+
funnel: { type: 'funnel', w: 300, stages: [{ label: 'Landing' }, { label: 'Sub' }] },
|
|
30
|
+
// device + product-UI kit
|
|
31
|
+
'device(iphone)': { type: 'device', kind: 'iphone', x: 0, y: 0 },
|
|
32
|
+
'device(ipad)': { type: 'device', kind: 'ipad', x: 0, y: 0 },
|
|
33
|
+
'device(mac)': { type: 'device', kind: 'mac', x: 0, y: 0 },
|
|
34
|
+
appBar: { type: 'appBar', w: 340, title: 'Ayarlar', back: true, actions: ['more-v'] },
|
|
35
|
+
tabBar: { type: 'tabBar', w: 340, items: [{ icon: 'home', label: 'Akış' }, { icon: 'user', label: 'Profil' }], active: 0 },
|
|
36
|
+
icon: { type: 'icon', name: 'search', size: 24 },
|
|
37
|
+
iconButton: { type: 'iconButton', icon: 'plus', shape: 'circle', variant: 'solid', color: 'blue' },
|
|
38
|
+
listRow: { type: 'listRow', w: 340, title: 'Bildirimler', trailing: 'toggle' },
|
|
39
|
+
toggle: { type: 'toggle', on: true },
|
|
40
|
+
segmented: { type: 'segmented', w: 300, items: ['Hepsi', 'Yeni'], active: 0 },
|
|
41
|
+
slider: { type: 'slider', w: 260, value: 0.4 },
|
|
42
|
+
searchField:{ type: 'searchField', w: 300, placeholder: 'Ara' },
|
|
43
|
+
windowFrame:{ type: 'windowFrame', w: 400, h: 260, kind: 'browser', url: 'acme.app' },
|
|
44
|
+
button: { type: 'button', w: 140, text: 'Kaydet' },
|
|
45
|
+
input: { type: 'input', w: 240, label: 'Slug', placeholder: 'chart-kit' },
|
|
46
|
+
imagePlaceholder: { type: 'imagePlaceholder', w: 200, h: 140 },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Degenerate input must not throw or divide by zero — empty series, single point, all-equal values.
|
|
50
|
+
const EDGE = {
|
|
51
|
+
'lineChart (boş seri)': { type: 'lineChart', w: 300, h: 200, series: [] },
|
|
52
|
+
'lineChart (tek nokta)': { type: 'lineChart', w: 300, h: 200, xLabels: ['1'], series: [{ label: 'a', points: [5] }] },
|
|
53
|
+
'barChart (hepsi eşit)': { type: 'barChart', w: 300, h: 200, bars: [{ label: 'a', value: 7 }, { label: 'b', value: 7 }] },
|
|
54
|
+
'donut (tek dilim)': { type: 'donut', r: 60, slices: [{ label: 'a', value: 1 }] },
|
|
55
|
+
'sparkline (boş)': { type: 'sparkline', w: 100, h: 30, points: [] },
|
|
56
|
+
'table (satır yok)': { type: 'table', headers: ['a', 'b'], rows: [] },
|
|
57
|
+
'tabBar (boş)': { type: 'tabBar', w: 300, items: [] },
|
|
58
|
+
'segmented (tek)': { type: 'segmented', w: 200, items: ['A'], active: 0 },
|
|
59
|
+
'icon (bilinmeyen ad)': { type: 'icon', name: 'yok-boyle-bir-sey', size: 20 },
|
|
60
|
+
'listRow (başlıksız)': { type: 'listRow', w: 300, title: '' },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const tmp = path.join(os.tmpdir(), 'excalidraw-atomic-check');
|
|
64
|
+
let pass = 0, fail = 0;
|
|
65
|
+
|
|
66
|
+
function check(label, el, requireElements = true) {
|
|
67
|
+
try {
|
|
68
|
+
const r = buildExcalidraw({ out: path.join(tmp, `${label.replace(/\W+/g, '-')}.excalidraw.md`), elements: [el] });
|
|
69
|
+
const bad = r.overlaps + r.buriedText + r.longLines;
|
|
70
|
+
const ok = bad === 0 && (!requireElements || r.elements > 0);
|
|
71
|
+
if (ok) { pass++; console.log(` ✓ ${label.padEnd(22)} ${String(r.elements).padStart(3)} element`); }
|
|
72
|
+
else { fail++; console.log(` ✗ ${label.padEnd(22)} elements=${r.elements} audit=${bad}`); }
|
|
73
|
+
} catch (e) {
|
|
74
|
+
fail++; console.log(` ✗ ${label.padEnd(22)} THREW: ${e.message.slice(0, 60)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log('\nEvery type from ONE spec element (data only, no JS):');
|
|
79
|
+
for (const [name, el] of Object.entries(CASES)) check(name, el);
|
|
80
|
+
|
|
81
|
+
console.log('\nDegenerate input must not throw:');
|
|
82
|
+
for (const [name, el] of Object.entries(EDGE)) check(name, el, false);
|
|
83
|
+
|
|
84
|
+
// dreamcontext contract: a board destined for knowledge/ must carry name + description, or it cannot
|
|
85
|
+
// be recalled. This is the integration that used to require hand-patching every generated file.
|
|
86
|
+
console.log('\nFrontmatter (dreamcontext recall contract):');
|
|
87
|
+
try {
|
|
88
|
+
const out = path.join(tmp, 'frontmatter.excalidraw.md');
|
|
89
|
+
buildExcalidraw({ out, name: 'demo-board', description: 'What this board shows.', tags: ['x', 'excalidraw'],
|
|
90
|
+
elements: [{ type: 'kpi', x: 0, y: 0, label: 'A', value: '1' }] });
|
|
91
|
+
const fm = require('fs').readFileSync(out, 'utf8').split('---')[1] || '';
|
|
92
|
+
const ok = /(^|\n)name: demo-board/.test(fm) && /(^|\n)description: >-/.test(fm)
|
|
93
|
+
&& /(^|\n)tags: \[x, excalidraw\]/.test(fm) && /excalidraw-plugin: parsed/.test(fm);
|
|
94
|
+
if (ok) { pass++; console.log(' ✓ name + description + tags emitted'); }
|
|
95
|
+
else { fail++; console.log(' ✗ frontmatter wrong:', JSON.stringify(fm.trim())); }
|
|
96
|
+
} catch (e) { fail++; console.log(' ✗ THREW:', e.message.slice(0, 60)); }
|
|
97
|
+
|
|
98
|
+
console.log(`\n ${pass} passed / ${fail} failed`);
|
|
99
|
+
process.exit(fail ? 1 : 0);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
{
|
|
2
|
+
"out": "./examples/Chart Spec.excalidraw.md",
|
|
3
|
+
"background": "#ffffff",
|
|
4
|
+
"elements": [
|
|
5
|
+
{
|
|
6
|
+
"type": "stack",
|
|
7
|
+
"x": 40,
|
|
8
|
+
"y": 40,
|
|
9
|
+
"gap": 40,
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"type": "sectionTitle",
|
|
13
|
+
"text": "Declarative charts — pure JSON, no generator script",
|
|
14
|
+
"fontSize": 34
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "row",
|
|
18
|
+
"gap": 24,
|
|
19
|
+
"items": [
|
|
20
|
+
{
|
|
21
|
+
"type": "kpi",
|
|
22
|
+
"w": 260,
|
|
23
|
+
"label": "D0 ROAS",
|
|
24
|
+
"value": "0.25",
|
|
25
|
+
"delta": "W1: 0.25 — değişmedi",
|
|
26
|
+
"color": "red"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"type": "kpi",
|
|
30
|
+
"w": 260,
|
|
31
|
+
"label": "CPM",
|
|
32
|
+
"value": "$169",
|
|
33
|
+
"delta": "+%22",
|
|
34
|
+
"color": "red",
|
|
35
|
+
"spark": [
|
|
36
|
+
139,
|
|
37
|
+
144,
|
|
38
|
+
151,
|
|
39
|
+
158,
|
|
40
|
+
169
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"type": "callout",
|
|
45
|
+
"w": 640,
|
|
46
|
+
"color": "gray",
|
|
47
|
+
"title": "tak diye",
|
|
48
|
+
"text": "Bu board tek bir JSON. Agent hiç JS yazmadan lineChart/barCompare/gantt çizebiliyor."
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"type": "row",
|
|
54
|
+
"gap": 50,
|
|
55
|
+
"items": [
|
|
56
|
+
{
|
|
57
|
+
"type": "lineChart",
|
|
58
|
+
"w": 620,
|
|
59
|
+
"h": 300,
|
|
60
|
+
"title": "lineChart — DAU",
|
|
61
|
+
"xLabels": [
|
|
62
|
+
"3",
|
|
63
|
+
"5",
|
|
64
|
+
"7",
|
|
65
|
+
"9",
|
|
66
|
+
"11",
|
|
67
|
+
"13",
|
|
68
|
+
"15"
|
|
69
|
+
],
|
|
70
|
+
"area": true,
|
|
71
|
+
"series": [
|
|
72
|
+
{
|
|
73
|
+
"label": "DAU",
|
|
74
|
+
"color": "blue",
|
|
75
|
+
"points": [
|
|
76
|
+
58,
|
|
77
|
+
69,
|
|
78
|
+
55,
|
|
79
|
+
44,
|
|
80
|
+
38,
|
|
81
|
+
35,
|
|
82
|
+
32
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "barCompare",
|
|
89
|
+
"w": 560,
|
|
90
|
+
"h": 300,
|
|
91
|
+
"title": "barCompare — W1 ↔ W2",
|
|
92
|
+
"seriesLabels": [
|
|
93
|
+
"W1",
|
|
94
|
+
"W2"
|
|
95
|
+
],
|
|
96
|
+
"colors": [
|
|
97
|
+
"gray",
|
|
98
|
+
"red"
|
|
99
|
+
],
|
|
100
|
+
"groups": [
|
|
101
|
+
{
|
|
102
|
+
"label": "CPM",
|
|
103
|
+
"values": [
|
|
104
|
+
139,
|
|
105
|
+
169
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"label": "Trans %",
|
|
110
|
+
"values": [
|
|
111
|
+
67.2,
|
|
112
|
+
46.77
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// chart_board.js — every chart in the kit, on one board.
|
|
2
|
+
// Data is FICTIONAL (a made-up product, "Acme"): this file ships to npm, so it demos the kit and
|
|
3
|
+
// must never carry real customer metrics.
|
|
4
|
+
// Run: node examples/chart_board.js → examples/Chart Kit.excalidraw.md (expects a clean audit)
|
|
5
|
+
//
|
|
6
|
+
// This doubles as the kit's smoke test: it drives every builder, and the build must report
|
|
7
|
+
// overlaps=0 buriedText=0 longLines=0. If a chart's geometry drifts, this board says so.
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { buildExcalidraw } = require(path.resolve(__dirname, '../scripts/build_excalidraw.js'));
|
|
10
|
+
const { sectionTitle, prose, stack, row, funnel, READ_W } = require(path.resolve(__dirname, '../scripts/lib/style.js'));
|
|
11
|
+
const {
|
|
12
|
+
lineChart, barChart, barCompare, stackedBar, gantt, quadrant,
|
|
13
|
+
donut, sparkline, heatmap, table, timeline, kpi, callout,
|
|
14
|
+
} = require(path.resolve(__dirname, '../scripts/lib/charts.js'));
|
|
15
|
+
|
|
16
|
+
const DAYS = ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'];
|
|
17
|
+
const DAU = [58, 74, 69, 64, 55, 47, 44, 41, 38, 36, 35, 33, 32];
|
|
18
|
+
const NEW = [44, 56, 51, 47, 40, 33, 30, 28, 26, 24, 23, 21, 20];
|
|
19
|
+
const PREM = [30, 35, 36, 38, 33, 27, 24, 21, 18, 15, 14, 12, 11];
|
|
20
|
+
|
|
21
|
+
const board = stack({
|
|
22
|
+
x: 60, y: 60, gap: 64, items: [
|
|
23
|
+
(x, y) => stack({
|
|
24
|
+
x, y, gap: 12, items: [
|
|
25
|
+
(x, y) => sectionTitle({ x, y, text: 'Excalidraw chart kit — every builder, one board', fontSize: 42 }),
|
|
26
|
+
(x, y) => prose({ x, y, width: READ_W, fontSize: 15, text: 'Each chart below is one call with DATA only — no coordinates, no hand-placed labels. Geometry, axes, wrapping and collision-avoidance belong to the builder.' }),
|
|
27
|
+
],
|
|
28
|
+
}),
|
|
29
|
+
|
|
30
|
+
// KPI tiles (with sparklines) + a callout
|
|
31
|
+
(x, y) => row({
|
|
32
|
+
x, y, gap: 24, items: [
|
|
33
|
+
(x, y) => kpi({ x, y, w: 300, label: 'DAU', value: '32', delta: 'peak 74 → -57%', color: 'red', spark: DAU }),
|
|
34
|
+
(x, y) => kpi({ x, y, w: 300, label: 'NEW USERS / DAY', value: '20', delta: '425 over 13 days', color: 'red', spark: NEW }),
|
|
35
|
+
(x, y) => kpi({ x, y, w: 300, label: 'D0 ROAS', value: '0.34', delta: 'W1: 0.31 — +10%', color: 'yellow' }),
|
|
36
|
+
(x, y) => callout({ x, y, w: 700, color: 'gray', title: 'callout()', text: 'Body copy is always bounded to the reading measure. A wide band puts its heading beside the text instead of stretching one line edge-to-edge.' }),
|
|
37
|
+
],
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
// lineChart + barCompare
|
|
41
|
+
(x, y) => row({
|
|
42
|
+
x, y, gap: 60, items: [
|
|
43
|
+
(x, y) => lineChart({
|
|
44
|
+
x, y, w: 760, h: 340, title: 'lineChart() — app health, days 1–13',
|
|
45
|
+
xLabels: DAYS, area: true,
|
|
46
|
+
series: [
|
|
47
|
+
{ label: 'DAU', color: 'blue', points: DAU },
|
|
48
|
+
{ label: 'new users', color: 'green', points: NEW },
|
|
49
|
+
{ label: 'paid actives', color: 'red', points: PREM },
|
|
50
|
+
],
|
|
51
|
+
}),
|
|
52
|
+
(x, y) => barCompare({
|
|
53
|
+
x, y, w: 700, h: 340, title: 'barCompare() — week 1 vs week 2',
|
|
54
|
+
seriesLabels: ['Week 1', 'Week 2'], colors: ['gray', 'red'],
|
|
55
|
+
groups: [
|
|
56
|
+
{ label: 'ROAS x100', values: [31, 34] },
|
|
57
|
+
{ label: 'CPM $', values: [120, 145] },
|
|
58
|
+
{ label: 'Checkout %', values: [72.0, 58.4] },
|
|
59
|
+
{ label: 'Refund x10', values: [18.0, 26.5] },
|
|
60
|
+
],
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
63
|
+
}),
|
|
64
|
+
|
|
65
|
+
// funnel + barChart(horizontal) + donut
|
|
66
|
+
(x, y) => row({
|
|
67
|
+
x, y, gap: 60, valign: 'top', items: [
|
|
68
|
+
(x, y) => funnel({
|
|
69
|
+
x, y, w: 420, topW: 420, botW: 120, stageH: 74, fontSize: 15, notes: false,
|
|
70
|
+
stages: [
|
|
71
|
+
{ label: 'Landing 4,000', color: 'blue' }, { label: 'Signup 1,900', color: 'red' },
|
|
72
|
+
{ label: 'Onboard 1,700', color: 'green' }, { label: 'Trial 1,200', color: 'red' },
|
|
73
|
+
{ label: 'Checkout 1,150', color: 'yellow' }, { label: 'Paid 140', color: 'red' },
|
|
74
|
+
],
|
|
75
|
+
}),
|
|
76
|
+
(x, y) => barChart({
|
|
77
|
+
x, y, w: 620, h: 320, horizontal: true, title: 'barChart({horizontal}) — signups by country',
|
|
78
|
+
bars: [
|
|
79
|
+
{ label: 'US', value: 310, color: 'blue' }, { label: 'DE', value: 64, color: 'yellow' },
|
|
80
|
+
{ label: 'UK', value: 52, color: 'gray' }, { label: 'CA', value: 41, color: 'gray' },
|
|
81
|
+
{ label: 'AU', value: 23, color: 'gray' },
|
|
82
|
+
],
|
|
83
|
+
}),
|
|
84
|
+
(x, y) => donut({
|
|
85
|
+
x, y, r: 120, title: 'donut() — error breakdown',
|
|
86
|
+
slices: [
|
|
87
|
+
{ label: 'timeout', value: 240, color: 'red' },
|
|
88
|
+
{ label: 'other', value: 60, color: 'gray' },
|
|
89
|
+
{ label: 'rate limited', value: 30, color: 'yellow' },
|
|
90
|
+
],
|
|
91
|
+
}),
|
|
92
|
+
],
|
|
93
|
+
}),
|
|
94
|
+
|
|
95
|
+
// stackedBar + quadrant
|
|
96
|
+
(x, y) => row({
|
|
97
|
+
x, y, gap: 60, valign: 'top', items: [
|
|
98
|
+
(x, y) => stackedBar({
|
|
99
|
+
x, y, w: 680, h: 340, title: 'stackedBar() — D1 cohort split',
|
|
100
|
+
seriesLabels: ['paid returned', 'free returned', 'churned'], colors: ['green', 'blue', 'gray'],
|
|
101
|
+
groups: [
|
|
102
|
+
{ label: 'week 1', values: [22, 14, 90] }, { label: 'week 2', values: [19, 12, 84] },
|
|
103
|
+
{ label: 'week 3', values: [17, 11, 96] },
|
|
104
|
+
],
|
|
105
|
+
}),
|
|
106
|
+
(x, y) => quadrant({
|
|
107
|
+
x, y, w: 620, h: 460, title: 'quadrant() — roadmap: impact x effort',
|
|
108
|
+
xAxis: { left: 'high effort', right: 'low effort' }, yAxis: { bottom: 'low impact', top: 'high impact' },
|
|
109
|
+
quadrantLabels: { tr: 'DO FIRST', tl: 'plan', br: 'quick win', bl: 'later' },
|
|
110
|
+
items: [
|
|
111
|
+
{ label: 'signup provisioning', x: 0.42, y: 0.95, color: 'red' },
|
|
112
|
+
{ label: 'checkout rate', x: 0.55, y: 0.88, color: 'red' },
|
|
113
|
+
{ label: 'landing A/B', x: 0.78, y: 0.66, color: 'yellow' },
|
|
114
|
+
{ label: 'churn-save', x: 0.35, y: 0.5, color: 'blue' },
|
|
115
|
+
{ label: 'refund monitor', x: 0.85, y: 0.28, color: 'gray' },
|
|
116
|
+
],
|
|
117
|
+
}),
|
|
118
|
+
],
|
|
119
|
+
}),
|
|
120
|
+
|
|
121
|
+
// gantt + timeline
|
|
122
|
+
(x, y) => gantt({
|
|
123
|
+
x, y, w: 1400, title: 'gantt() — fix plan', today: '2026-03-02',
|
|
124
|
+
tasks: [
|
|
125
|
+
{ label: 'backend cross-check', start: '2026-03-02', end: '2026-03-05', color: 'red', done: 0.3 },
|
|
126
|
+
{ label: 'payment triage', start: '2026-03-03', end: '2026-03-09', color: 'red' },
|
|
127
|
+
{ label: 'landing A/B', start: '2026-03-06', end: '2026-03-16', color: 'yellow' },
|
|
128
|
+
{ label: 'churn-save flow', start: '2026-03-10', end: '2026-03-22', color: 'blue' },
|
|
129
|
+
{ label: 'review', start: '2026-03-09', milestone: true, color: 'purple' },
|
|
130
|
+
],
|
|
131
|
+
}),
|
|
132
|
+
(x, y) => timeline({
|
|
133
|
+
x, y, w: 1400, title: 'timeline() — campaign events',
|
|
134
|
+
events: [
|
|
135
|
+
{ label: 'Campaign start', at: '2026-02-17', color: 'blue' },
|
|
136
|
+
{ label: 'Pricing change', at: '2026-02-22', color: 'yellow' },
|
|
137
|
+
{ label: 'Budget cut 67%', at: '2026-02-23', color: 'red' },
|
|
138
|
+
{ label: 'Checkout dropped', at: '2026-02-26', color: 'red' },
|
|
139
|
+
{ label: 'Review', at: '2026-03-02', color: 'purple' },
|
|
140
|
+
],
|
|
141
|
+
}),
|
|
142
|
+
|
|
143
|
+
// heatmap + table
|
|
144
|
+
(x, y) => row({
|
|
145
|
+
x, y, gap: 60, valign: 'top', items: [
|
|
146
|
+
(x, y) => heatmap({
|
|
147
|
+
x, y, title: 'heatmap() — retention, cohort x day', cell: 40,
|
|
148
|
+
rows: ['week 1', 'week 2', 'week 3', 'week 4', 'week 5'],
|
|
149
|
+
cols: ['D0', 'D1', 'D2', 'D3', 'D4'],
|
|
150
|
+
values: [
|
|
151
|
+
[100, 11, 7, 5, 4], [100, 9, 6, 4, 3], [100, 13, 8, 6, 4],
|
|
152
|
+
[100, 8, 5, 4, null], [100, 27, 12, null, null],
|
|
153
|
+
],
|
|
154
|
+
fmt: (v) => (v == null ? '' : v + '%'),
|
|
155
|
+
}),
|
|
156
|
+
(x, y) => table({
|
|
157
|
+
x, y, title: 'table() — plan comparison',
|
|
158
|
+
headers: ['Plan', 'Churn', 'MRR', 'Seats'],
|
|
159
|
+
align: ['left', 'right', 'right', 'right'],
|
|
160
|
+
rows: [
|
|
161
|
+
['Free', { text: '9.1%', color: 'red' }, '$0', '1,240'],
|
|
162
|
+
['Pro', { text: '3.4%', color: 'yellow' }, '$18,400', '460'],
|
|
163
|
+
['Team', { text: '1.8%', color: 'green' }, '$42,900', '210'],
|
|
164
|
+
['Enterprise', { text: '0.9%', color: 'green' }, '$96,000', '48'],
|
|
165
|
+
],
|
|
166
|
+
}),
|
|
167
|
+
],
|
|
168
|
+
}),
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const res = buildExcalidraw({ out: path.resolve(__dirname, 'Chart Kit.excalidraw.md'), elements: board });
|
|
173
|
+
console.log(`elements=${res.elements} texts=${res.texts} overlaps=${res.overlaps} buriedText=${res.buriedText} longLines=${res.longLines}`);
|
|
@@ -2,13 +2,83 @@
|
|
|
2
2
|
"out": "examples/Hello Excalidraw.excalidraw.md",
|
|
3
3
|
"background": "#ffffff",
|
|
4
4
|
"elements": [
|
|
5
|
-
{
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
{
|
|
6
|
+
"type": "text",
|
|
7
|
+
"x": 0,
|
|
8
|
+
"y": -70,
|
|
9
|
+
"text": "excalidraw skill — portable smoke test",
|
|
10
|
+
"fontSize": 28,
|
|
11
|
+
"color": "#1971c2"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "text",
|
|
15
|
+
"x": 0,
|
|
16
|
+
"y": -28,
|
|
17
|
+
"text": "Give a text a width and it wraps to that width (no overlap). The image embeds via sha1 wikilink — no base64. Only skill-relative paths, so this runs in any project.",
|
|
18
|
+
"fontSize": 15,
|
|
19
|
+
"color": "#868e96",
|
|
20
|
+
"width": 540
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": "rectangle",
|
|
24
|
+
"x": 0,
|
|
25
|
+
"y": 40,
|
|
26
|
+
"width": 260,
|
|
27
|
+
"height": 140,
|
|
28
|
+
"strokeColor": "#1e1e1e",
|
|
29
|
+
"backgroundColor": "#a5d8ff",
|
|
30
|
+
"fillStyle": "solid",
|
|
31
|
+
"strokeWidth": 2,
|
|
32
|
+
"roundness": true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "text",
|
|
36
|
+
"x": 24,
|
|
37
|
+
"y": 96,
|
|
38
|
+
"text": "rounded rect\n+ fill",
|
|
39
|
+
"fontSize": 20,
|
|
40
|
+
"color": "#1e1e1e"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "ellipse",
|
|
44
|
+
"x": 340,
|
|
45
|
+
"y": 40,
|
|
46
|
+
"width": 160,
|
|
47
|
+
"height": 140,
|
|
48
|
+
"strokeColor": "#2f9e44",
|
|
49
|
+
"backgroundColor": "#b2f2bb",
|
|
50
|
+
"fillStyle": "hachure"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"type": "arrow",
|
|
54
|
+
"points": [
|
|
55
|
+
[
|
|
56
|
+
260,
|
|
57
|
+
110
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
340,
|
|
61
|
+
110
|
|
62
|
+
]
|
|
63
|
+
],
|
|
64
|
+
"strokeColor": "#e8590c",
|
|
65
|
+
"strokeWidth": 3
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"type": "text",
|
|
69
|
+
"x": 0,
|
|
70
|
+
"y": 220,
|
|
71
|
+
"text": "embedded image (resolved from vault by sha1 wikilink):",
|
|
72
|
+
"fontSize": 16,
|
|
73
|
+
"color": "#555",
|
|
74
|
+
"width": 540
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "image",
|
|
78
|
+
"x": 0,
|
|
79
|
+
"y": 250,
|
|
80
|
+
"path": "examples/sample.png",
|
|
81
|
+
"width": 320
|
|
82
|
+
}
|
|
13
83
|
]
|
|
14
|
-
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// visual_board.js — the visual-first kit demo. Run from anywhere: node examples/visual_board.js
|
|
2
|
+
// Shows the three rules in action: a trapezoid FUNNEL, a browser PROTOTYPE assembled purely with
|
|
3
|
+
// stack()/row() flow layout (no hand-computed coordinates → no overlap), and READABLE prose/bullets
|
|
4
|
+
// that wrap to a bounded measure instead of stretching across the whole board.
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { buildExcalidraw } = require(path.join(__dirname, '..', 'scripts', 'build_excalidraw.js'));
|
|
7
|
+
const {
|
|
8
|
+
sectionTitle, prose, bullets, funnel,
|
|
9
|
+
windowFrame, navbar, button, textRows, imagePlaceholder,
|
|
10
|
+
stack, row,
|
|
11
|
+
} = require(path.join(__dirname, '..', 'scripts', 'lib', 'style.js'));
|
|
12
|
+
|
|
13
|
+
const els = [];
|
|
14
|
+
const P = (...a) => els.push(...a.flat());
|
|
15
|
+
|
|
16
|
+
P(sectionTitle({ x: 60, y: 40, text: 'Visual-first kit — funnel · prototype · readable text', fontSize: 32 }));
|
|
17
|
+
|
|
18
|
+
// ── FUNNEL (left) — filled trapezoid bands, each with a right-margin metric note ──
|
|
19
|
+
P(sectionTitle({ x: 60, y: 118, text: 'Conversion funnel', fontSize: 20, color: '#868e96' }));
|
|
20
|
+
P(funnel({
|
|
21
|
+
x: 60, y: 168, w: 440, stageH: 80,
|
|
22
|
+
stages: [
|
|
23
|
+
{ label: 'Visitors', note: '100% · 48,200 sessions', color: 'blue' },
|
|
24
|
+
{ label: 'Signups', note: '32% · quality-gated', color: 'purple' },
|
|
25
|
+
{ label: 'Activated', note: '18% · reached first value', color: 'yellow' },
|
|
26
|
+
{ label: 'Paying', note: '6% · $29 / mo', color: 'mint' },
|
|
27
|
+
],
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
// ── PROTOTYPE (right) — a browser wireframe; every child placed by flow layout ──
|
|
31
|
+
const win = windowFrame({ x: 900, y: 118, w: 680, h: 560, kind: 'browser', url: 'https://acme.app/pricing' });
|
|
32
|
+
P(win);
|
|
33
|
+
const I = win.inner;
|
|
34
|
+
P(navbar({ x: I.x, y: I.y, w: I.w, brand: 'Acme', items: ['Product', 'Pricing', 'Docs'], cta: 'Sign up' }));
|
|
35
|
+
|
|
36
|
+
// hero: copy column + image, flowed side by side (row can't let them overlap)
|
|
37
|
+
const hero = row({
|
|
38
|
+
x: I.x, y: I.y + 74, gap: 28, valign: 'top',
|
|
39
|
+
items: [
|
|
40
|
+
(x, y) => stack({
|
|
41
|
+
x, y, gap: 14, items: [
|
|
42
|
+
(hx, hy) => prose({ x: hx, y: hy, text: 'The persistent brain for your agents', fontSize: 24, width: 320 }),
|
|
43
|
+
(hx, hy) => textRows({ x: hx, y: hy, w: 320, rows: 3 }),
|
|
44
|
+
(hx, hy) => button({ x: hx, y: hy, w: 160, h: 42, text: 'Get started', color: 'blue' }),
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
(x, y) => imagePlaceholder({ x, y, w: 236, h: 158, label: 'product shot' }),
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
P(hero);
|
|
51
|
+
|
|
52
|
+
// three feature tiles, flowed left→right
|
|
53
|
+
const tiles = row({
|
|
54
|
+
x: I.x, y: hero.nextY + 28, gap: 18,
|
|
55
|
+
items: [['Remember', 'green'], ['Recall', 'purple'], ['Act', 'mint']].map(([t]) => (x, y) => stack({
|
|
56
|
+
x, y, gap: 8, items: [
|
|
57
|
+
(ax, ay) => imagePlaceholder({ x: ax, y: ay, w: 190, h: 72 }),
|
|
58
|
+
(ax, ay) => prose({ x: ax, y: ay, text: t, fontSize: 16, width: 190 }),
|
|
59
|
+
(ax, ay) => textRows({ x: ax, y: ay, w: 190, rows: 2 }),
|
|
60
|
+
],
|
|
61
|
+
})),
|
|
62
|
+
});
|
|
63
|
+
P(tiles);
|
|
64
|
+
|
|
65
|
+
// ── READABLE MEASURE (bottom-left) — text that wraps to a column, not the canvas ──
|
|
66
|
+
P(sectionTitle({ x: 60, y: 600, text: 'Readable measure', fontSize: 20, color: '#868e96' }));
|
|
67
|
+
P(prose({
|
|
68
|
+
x: 60, y: 646, width: 620, fontSize: 18,
|
|
69
|
+
text: 'Body text wraps to a bounded reading width (~60 characters) instead of stretching across the whole board. Long passages stay in a comfortable column, so the eye never has to travel the full width of a wide canvas to find the start of the next line — that is what keeps a text block legible.',
|
|
70
|
+
}));
|
|
71
|
+
P(bullets({
|
|
72
|
+
x: 60, y: 792, width: 620, fontSize: 18,
|
|
73
|
+
items: [
|
|
74
|
+
'Prefer pictures — funnels, wireframes, placeholders — over paragraphs.',
|
|
75
|
+
'When you do write, cap the measure with prose() / bullets() so nothing runs edge to edge.',
|
|
76
|
+
'Lay out with stack() / row() so boxes flow and never overlap; the build step also audits and warns.',
|
|
77
|
+
],
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
const out = path.join(__dirname, 'Visual Kit.excalidraw.md');
|
|
81
|
+
const res = buildExcalidraw({ out, elements: els, background: '#ffffff' });
|
|
82
|
+
console.log('visual demo →', out, '| overlaps:', res.overlaps);
|