@taprootio/espalier 2.15.4 → 2.16.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/custom-elements.json
CHANGED
|
@@ -19434,368 +19434,6 @@
|
|
|
19434
19434
|
}
|
|
19435
19435
|
]
|
|
19436
19436
|
},
|
|
19437
|
-
{
|
|
19438
|
-
"kind": "javascript-module",
|
|
19439
|
-
"path": "dist/form/esp-form.js",
|
|
19440
|
-
"declarations": [
|
|
19441
|
-
{
|
|
19442
|
-
"kind": "class",
|
|
19443
|
-
"description": "A form wrapper that renders a native `<form>` element in\nthe light DOM. All form-associated custom elements placed\ninside participate natively in form submission, validation,\nand reset.\n\n`esp-form` has no visual presentation of its own — all\nstyling, labels, and layout should be handled independently\n(e.g. via [esp-form-item](/components/form-item), `esp-box`,\nor plain CSS).\n\n### Standard submission\n\n```html\n<esp-form action=\"/api/save\" method=\"post\" label=\"Contact form\">\n <esp-form-item label=\"Name\">\n <esp-input name=\"name\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Send\"></esp-button>\n</esp-form>\n```\n\n### Fetch submission\n\n```html\n<esp-form action=\"/api/save\" use-fetch use-json label=\"Settings\">\n <esp-form-item label=\"Email\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Save\"></esp-button>\n</esp-form>\n```\n\n### Dialog integration\n\nWhen `method=\"dialog\"`, submitting the form dispatches a\n`closeDialog` event that `esp-dialog` listens for, closing\nthe dialog without a network request.\n\n### Multi-field form with validation\n\nRequired fields are validated on submit. The first invalid\nfield is scrolled into view and focused. Errors clear as\nthe user corrects each field. Use the `required-message`\nattribute on any form control to customize the error text.\n\n```html\n<style>\nesp-form.signup-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.signup-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"signup-demo\" use-fetch use-json action=\"/api/signup\" label=\"Sign up\">\n <esp-form-item label=\"Full name\">\n <esp-input name=\"fullName\" required required-message=\"We need your full name.\"></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Email address\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Password\">\n <esp-input name=\"password\" input-type=\"password\" required required-message=\"You must enter a password to continue!\"></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Favorite color\">\n <esp-pick-one name=\"color\" required placeholder=\"Pick one...\" required-message=\"Please choose your favorite color.\">\n <esp-picker-item text=\"Red\" value=\"red\"></esp-picker-item>\n <esp-picker-item text=\"Green\" value=\"green\"></esp-picker-item>\n <esp-picker-item text=\"Blue\" value=\"blue\"></esp-picker-item>\n </esp-pick-one>\n </esp-form-item>\n <esp-form-item label=\"I agree to the terms\">\n <esp-checkbox name=\"terms\" value=\"agreed\" required required-message=\"You must accept the terms to continue.\">\n Yes, I accept\n </esp-checkbox>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Sign Up\"></esp-button>\n <esp-button button-type=\"reset\" label=\"Reset\" variant=\"danger\"></esp-button>\n </div>\n</esp-form>\n```\n\n### Skipping validation\n\nAdd `formnovalidate` to a submit button to bypass constraint\nvalidation. This is useful for \"Save Draft\" buttons that\nshould persist incomplete data.\n\n```html\n<style>\nesp-form.draft-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.draft-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"draft-demo\" use-fetch use-json action=\"/api/drafts\" label=\"Article editor\">\n <esp-form-item label=\"Title\">\n <esp-input name=\"title\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Category\">\n <esp-pick-one name=\"category\" required placeholder=\"Select...\">\n <esp-picker-item text=\"Technology\" value=\"tech\"></esp-picker-item>\n <esp-picker-item text=\"Design\" value=\"design\"></esp-picker-item>\n <esp-picker-item text=\"Business\" value=\"biz\"></esp-picker-item>\n </esp-pick-one>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Publish\"></esp-button>\n <esp-button button-type=\"submit\" formnovalidate label=\"Save Draft\" variant=\"split-complementary-left\"></esp-button>\n </div>\n</esp-form>\n```\n\n### Handling the response\n\nListen for `esp-submit-response` and `esp-submit-error` to\nreact to the server's reply when using fetch submission.\n\n```html\n<style>\nesp-form.response-demo { display: grid; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"response-demo\" use-fetch use-json action=\"/api/feedback\" label=\"Feedback\">\n <esp-form-item label=\"Your feedback\">\n <esp-input name=\"message\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Send Feedback\"></esp-button>\n <esp-info id=\"response-msg\" icon=\"info-i\" style=\"display:none\">\n <span id=\"response-text\"></span>\n </esp-info>\n</esp-form>\n<script>\n const form = findByTagName(\"esp-form\")[0];\n const msg = findById(\"response-msg\");\n const text = findById(\"response-text\");\n form.addEventListener(\"esp-submit-response\", (ev) => {\n msg.style.display = \"\";\n msg.setAttribute(\"variant\", ev.detail.ok ? \"success\" : \"warning\");\n text.textContent = ev.detail.ok\n ? \"Submitted successfully!\"\n : \"Server returned an error.\";\n });\n form.addEventListener(\"esp-submit-error\", () => {\n msg.style.display = \"\";\n msg.setAttribute(\"variant\", \"danger\");\n text.textContent = \"Network error — please try again.\";\n });\n</script>\n```\n\n### Form with diverse input types\n\nCombines email, telephone, number, and date inputs with\nvalidation and custom messages.\n\n```html\n<style>\nesp-form.diverse-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.diverse-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"diverse-demo\" use-fetch use-json action=\"/api/contact\" label=\"Contact info\">\n <esp-form-item label=\"Email\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Phone\">\n <esp-input name=\"phone\" input-type=\"tel\"\n tel-localities=\"US CA GB\" required>\n </esp-input>\n </esp-form-item>\n <esp-form-item label=\"Age\">\n <esp-input name=\"age\" input-type=\"number\"\n min=\"0\" max=\"150\" required>\n </esp-input>\n </esp-form-item>\n <esp-form-item label=\"Date of birth\">\n <esp-input name=\"dob\" input-type=\"date\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Comments\">\n <esp-textarea name=\"comments\" rows=\"3\"\n placeholder=\"Any additional comments...\">\n </esp-textarea>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Submit\"></esp-button>\n <esp-button button-type=\"reset\" label=\"Reset\" variant=\"danger\"></esp-button>\n </div>\n</esp-form>\n```",
|
|
19444
|
-
"name": "EspalierForm",
|
|
19445
|
-
"members": [
|
|
19446
|
-
{
|
|
19447
|
-
"kind": "field",
|
|
19448
|
-
"name": "_form",
|
|
19449
|
-
"type": {
|
|
19450
|
-
"text": "HTMLFormElement"
|
|
19451
|
-
},
|
|
19452
|
-
"privacy": "private"
|
|
19453
|
-
},
|
|
19454
|
-
{
|
|
19455
|
-
"kind": "field",
|
|
19456
|
-
"name": "_formReady",
|
|
19457
|
-
"type": {
|
|
19458
|
-
"text": "boolean"
|
|
19459
|
-
},
|
|
19460
|
-
"privacy": "private",
|
|
19461
|
-
"default": "false"
|
|
19462
|
-
},
|
|
19463
|
-
{
|
|
19464
|
-
"kind": "field",
|
|
19465
|
-
"name": "action",
|
|
19466
|
-
"type": {
|
|
19467
|
-
"text": "string"
|
|
19468
|
-
},
|
|
19469
|
-
"privacy": "public",
|
|
19470
|
-
"default": "\"\"",
|
|
19471
|
-
"description": "The URL that processes the form submission. When `use-fetch`\nis true this is the URL `fetch()` sends the request to.",
|
|
19472
|
-
"attribute": "action"
|
|
19473
|
-
},
|
|
19474
|
-
{
|
|
19475
|
-
"kind": "field",
|
|
19476
|
-
"name": "method",
|
|
19477
|
-
"type": {
|
|
19478
|
-
"text": "string"
|
|
19479
|
-
},
|
|
19480
|
-
"privacy": "public",
|
|
19481
|
-
"default": "\"post\"",
|
|
19482
|
-
"description": "The HTTP method for submission. Standard values are `get`,\n`post`, and `dialog`. When set to `dialog`, submitting the\nform closes the nearest `esp-dialog` ancestor without making\na network request.",
|
|
19483
|
-
"attribute": "method"
|
|
19484
|
-
},
|
|
19485
|
-
{
|
|
19486
|
-
"kind": "field",
|
|
19487
|
-
"name": "novalidate",
|
|
19488
|
-
"type": {
|
|
19489
|
-
"text": "boolean"
|
|
19490
|
-
},
|
|
19491
|
-
"privacy": "public",
|
|
19492
|
-
"default": "false",
|
|
19493
|
-
"description": "When true, constraint validation is skipped during\nsubmission.",
|
|
19494
|
-
"attribute": "novalidate"
|
|
19495
|
-
},
|
|
19496
|
-
{
|
|
19497
|
-
"kind": "field",
|
|
19498
|
-
"name": "useFetch",
|
|
19499
|
-
"type": {
|
|
19500
|
-
"text": "boolean"
|
|
19501
|
-
},
|
|
19502
|
-
"privacy": "public",
|
|
19503
|
-
"default": "false",
|
|
19504
|
-
"description": "When true, the form uses `fetch()` instead of native\nbrowser navigation for submission. An `esp-submit` event\nis fired with the `FormData` in the detail, allowing\nconsumers to cancel or modify the request.",
|
|
19505
|
-
"attribute": "use-fetch"
|
|
19506
|
-
},
|
|
19507
|
-
{
|
|
19508
|
-
"kind": "field",
|
|
19509
|
-
"name": "useJson",
|
|
19510
|
-
"type": {
|
|
19511
|
-
"text": "boolean"
|
|
19512
|
-
},
|
|
19513
|
-
"privacy": "public",
|
|
19514
|
-
"default": "false",
|
|
19515
|
-
"description": "When `use-fetch` is true and this is also true, the request\nbody is serialized as JSON instead of `FormData`.",
|
|
19516
|
-
"attribute": "use-json"
|
|
19517
|
-
},
|
|
19518
|
-
{
|
|
19519
|
-
"kind": "field",
|
|
19520
|
-
"name": "enctype",
|
|
19521
|
-
"type": {
|
|
19522
|
-
"text": "string"
|
|
19523
|
-
},
|
|
19524
|
-
"privacy": "public",
|
|
19525
|
-
"default": "\"application/x-www-form-urlencoded\"",
|
|
19526
|
-
"description": "The encoding type for form submission. Maps to the native\n`enctype` attribute on the inner `<form>`.",
|
|
19527
|
-
"attribute": "enctype"
|
|
19528
|
-
},
|
|
19529
|
-
{
|
|
19530
|
-
"kind": "field",
|
|
19531
|
-
"name": "label",
|
|
19532
|
-
"type": {
|
|
19533
|
-
"text": "string"
|
|
19534
|
-
},
|
|
19535
|
-
"privacy": "public",
|
|
19536
|
-
"default": "\"\"",
|
|
19537
|
-
"description": "An accessible label applied as `aria-label` on the inner\n`<form>` element so the form is discoverable as an ARIA\n`form` landmark by screen readers.",
|
|
19538
|
-
"attribute": "label"
|
|
19539
|
-
},
|
|
19540
|
-
{
|
|
19541
|
-
"kind": "method",
|
|
19542
|
-
"name": "syncFormAttributes",
|
|
19543
|
-
"privacy": "private",
|
|
19544
|
-
"return": {
|
|
19545
|
-
"type": {
|
|
19546
|
-
"text": "void"
|
|
19547
|
-
}
|
|
19548
|
-
}
|
|
19549
|
-
},
|
|
19550
|
-
{
|
|
19551
|
-
"kind": "method",
|
|
19552
|
-
"name": "checkValidity",
|
|
19553
|
-
"privacy": "public",
|
|
19554
|
-
"return": {
|
|
19555
|
-
"type": {
|
|
19556
|
-
"text": "boolean"
|
|
19557
|
-
}
|
|
19558
|
-
},
|
|
19559
|
-
"description": "Run constraint validation on all controls without showing\nany UI feedback."
|
|
19560
|
-
},
|
|
19561
|
-
{
|
|
19562
|
-
"kind": "method",
|
|
19563
|
-
"name": "reportValidity",
|
|
19564
|
-
"privacy": "public",
|
|
19565
|
-
"return": {
|
|
19566
|
-
"type": {
|
|
19567
|
-
"text": ""
|
|
19568
|
-
}
|
|
19569
|
-
},
|
|
19570
|
-
"description": "Run constraint validation, display error messages via each\ncontrol's `esp-form-item`, and scroll the first invalid\nitem into view."
|
|
19571
|
-
},
|
|
19572
|
-
{
|
|
19573
|
-
"kind": "method",
|
|
19574
|
-
"name": "reset",
|
|
19575
|
-
"privacy": "public",
|
|
19576
|
-
"return": {
|
|
19577
|
-
"type": {
|
|
19578
|
-
"text": "void"
|
|
19579
|
-
}
|
|
19580
|
-
},
|
|
19581
|
-
"description": "Programmatically reset the form and all its controls."
|
|
19582
|
-
},
|
|
19583
|
-
{
|
|
19584
|
-
"kind": "method",
|
|
19585
|
-
"name": "submit",
|
|
19586
|
-
"privacy": "public",
|
|
19587
|
-
"return": {
|
|
19588
|
-
"type": {
|
|
19589
|
-
"text": "void"
|
|
19590
|
-
}
|
|
19591
|
-
},
|
|
19592
|
-
"description": "Programmatically trigger form submission (with validation)."
|
|
19593
|
-
},
|
|
19594
|
-
{
|
|
19595
|
-
"kind": "method",
|
|
19596
|
-
"name": "handleSubmit",
|
|
19597
|
-
"privacy": "private",
|
|
19598
|
-
"return": {
|
|
19599
|
-
"type": {
|
|
19600
|
-
"text": "void"
|
|
19601
|
-
}
|
|
19602
|
-
},
|
|
19603
|
-
"parameters": [
|
|
19604
|
-
{
|
|
19605
|
-
"name": "ev",
|
|
19606
|
-
"type": {
|
|
19607
|
-
"text": "SubmitEvent"
|
|
19608
|
-
}
|
|
19609
|
-
}
|
|
19610
|
-
]
|
|
19611
|
-
},
|
|
19612
|
-
{
|
|
19613
|
-
"kind": "method",
|
|
19614
|
-
"name": "handleKeyDown",
|
|
19615
|
-
"privacy": "private",
|
|
19616
|
-
"return": {
|
|
19617
|
-
"type": {
|
|
19618
|
-
"text": "void"
|
|
19619
|
-
}
|
|
19620
|
-
},
|
|
19621
|
-
"parameters": [
|
|
19622
|
-
{
|
|
19623
|
-
"name": "ev",
|
|
19624
|
-
"type": {
|
|
19625
|
-
"text": "KeyboardEvent"
|
|
19626
|
-
}
|
|
19627
|
-
}
|
|
19628
|
-
]
|
|
19629
|
-
},
|
|
19630
|
-
{
|
|
19631
|
-
"kind": "method",
|
|
19632
|
-
"name": "submitViaFetch",
|
|
19633
|
-
"privacy": "private",
|
|
19634
|
-
"return": {
|
|
19635
|
-
"type": {
|
|
19636
|
-
"text": "Promise<void>"
|
|
19637
|
-
}
|
|
19638
|
-
},
|
|
19639
|
-
"parameters": [
|
|
19640
|
-
{
|
|
19641
|
-
"name": "form",
|
|
19642
|
-
"type": {
|
|
19643
|
-
"text": "HTMLFormElement"
|
|
19644
|
-
}
|
|
19645
|
-
}
|
|
19646
|
-
]
|
|
19647
|
-
},
|
|
19648
|
-
{
|
|
19649
|
-
"kind": "field",
|
|
19650
|
-
"name": "noValidate",
|
|
19651
|
-
"type": {
|
|
19652
|
-
"text": "boolean"
|
|
19653
|
-
},
|
|
19654
|
-
"default": "true"
|
|
19655
|
-
}
|
|
19656
|
-
],
|
|
19657
|
-
"events": [
|
|
19658
|
-
{
|
|
19659
|
-
"name": "closeDialog",
|
|
19660
|
-
"type": {
|
|
19661
|
-
"text": "CustomEvent"
|
|
19662
|
-
},
|
|
19663
|
-
"description": "Fired when `method=\"dialog\"` is used and the form requests its containing `<esp-dialog>` to close. The event detail is an empty object."
|
|
19664
|
-
},
|
|
19665
|
-
{
|
|
19666
|
-
"name": "esp-submit-response",
|
|
19667
|
-
"type": {
|
|
19668
|
-
"text": "CustomEvent<{ response: Response; ok: boolean }>"
|
|
19669
|
-
},
|
|
19670
|
-
"description": "Fired after a successful `fetch` submission."
|
|
19671
|
-
},
|
|
19672
|
-
{
|
|
19673
|
-
"name": "esp-submit-error",
|
|
19674
|
-
"type": {
|
|
19675
|
-
"text": "CustomEvent<{ error: unknown }>"
|
|
19676
|
-
},
|
|
19677
|
-
"description": "Fired when a `fetch` submission fails."
|
|
19678
|
-
},
|
|
19679
|
-
{
|
|
19680
|
-
"type": {
|
|
19681
|
-
"text": "CustomEvent<{ formData: FormData; form: HTMLFormElement }>"
|
|
19682
|
-
},
|
|
19683
|
-
"description": "Fired when `use-fetch` is true and the form passes validation. Cancelable; calling `preventDefault()` aborts the fetch.",
|
|
19684
|
-
"name": "esp-submit"
|
|
19685
|
-
}
|
|
19686
|
-
],
|
|
19687
|
-
"attributes": [
|
|
19688
|
-
{
|
|
19689
|
-
"name": "action",
|
|
19690
|
-
"type": {
|
|
19691
|
-
"text": "string"
|
|
19692
|
-
},
|
|
19693
|
-
"default": "\"\"",
|
|
19694
|
-
"description": "The URL that processes the form submission. When `use-fetch`\nis true this is the URL `fetch()` sends the request to.",
|
|
19695
|
-
"fieldName": "action"
|
|
19696
|
-
},
|
|
19697
|
-
{
|
|
19698
|
-
"name": "method",
|
|
19699
|
-
"type": {
|
|
19700
|
-
"text": "string"
|
|
19701
|
-
},
|
|
19702
|
-
"default": "\"post\"",
|
|
19703
|
-
"description": "The HTTP method for submission. Standard values are `get`,\n`post`, and `dialog`. When set to `dialog`, submitting the\nform closes the nearest `esp-dialog` ancestor without making\na network request.",
|
|
19704
|
-
"fieldName": "method"
|
|
19705
|
-
},
|
|
19706
|
-
{
|
|
19707
|
-
"name": "novalidate",
|
|
19708
|
-
"type": {
|
|
19709
|
-
"text": "boolean"
|
|
19710
|
-
},
|
|
19711
|
-
"default": "false",
|
|
19712
|
-
"description": "When true, constraint validation is skipped during\nsubmission.",
|
|
19713
|
-
"fieldName": "novalidate"
|
|
19714
|
-
},
|
|
19715
|
-
{
|
|
19716
|
-
"name": "use-fetch",
|
|
19717
|
-
"type": {
|
|
19718
|
-
"text": "boolean"
|
|
19719
|
-
},
|
|
19720
|
-
"default": "false",
|
|
19721
|
-
"description": "When true, the form uses `fetch()` instead of native\nbrowser navigation for submission. An `esp-submit` event\nis fired with the `FormData` in the detail, allowing\nconsumers to cancel or modify the request.",
|
|
19722
|
-
"fieldName": "useFetch"
|
|
19723
|
-
},
|
|
19724
|
-
{
|
|
19725
|
-
"name": "use-json",
|
|
19726
|
-
"type": {
|
|
19727
|
-
"text": "boolean"
|
|
19728
|
-
},
|
|
19729
|
-
"default": "false",
|
|
19730
|
-
"description": "When `use-fetch` is true and this is also true, the request\nbody is serialized as JSON instead of `FormData`.",
|
|
19731
|
-
"fieldName": "useJson"
|
|
19732
|
-
},
|
|
19733
|
-
{
|
|
19734
|
-
"name": "enctype",
|
|
19735
|
-
"type": {
|
|
19736
|
-
"text": "string"
|
|
19737
|
-
},
|
|
19738
|
-
"default": "\"application/x-www-form-urlencoded\"",
|
|
19739
|
-
"description": "The encoding type for form submission. Maps to the native\n`enctype` attribute on the inner `<form>`.",
|
|
19740
|
-
"fieldName": "enctype"
|
|
19741
|
-
},
|
|
19742
|
-
{
|
|
19743
|
-
"name": "label",
|
|
19744
|
-
"type": {
|
|
19745
|
-
"text": "string"
|
|
19746
|
-
},
|
|
19747
|
-
"default": "\"\"",
|
|
19748
|
-
"description": "An accessible label applied as `aria-label` on the inner\n`<form>` element so the form is discoverable as an ARIA\n`form` landmark by screen readers.",
|
|
19749
|
-
"fieldName": "label"
|
|
19750
|
-
}
|
|
19751
|
-
],
|
|
19752
|
-
"superclass": {
|
|
19753
|
-
"name": "LitElement",
|
|
19754
|
-
"package": "lit"
|
|
19755
|
-
},
|
|
19756
|
-
"tagName": "esp-form",
|
|
19757
|
-
"customElement": true,
|
|
19758
|
-
"docPageTitle": {
|
|
19759
|
-
"name": "Form",
|
|
19760
|
-
"description": ""
|
|
19761
|
-
},
|
|
19762
|
-
"docUrl": {
|
|
19763
|
-
"name": "/components/form",
|
|
19764
|
-
"description": ""
|
|
19765
|
-
},
|
|
19766
|
-
"menuGroup": {
|
|
19767
|
-
"name": "Form",
|
|
19768
|
-
"description": "Controls"
|
|
19769
|
-
},
|
|
19770
|
-
"menuLabel": {
|
|
19771
|
-
"name": "Form",
|
|
19772
|
-
"description": ""
|
|
19773
|
-
},
|
|
19774
|
-
"menuIcon": {
|
|
19775
|
-
"name": "forms",
|
|
19776
|
-
"description": ""
|
|
19777
|
-
}
|
|
19778
|
-
}
|
|
19779
|
-
],
|
|
19780
|
-
"exports": [
|
|
19781
|
-
{
|
|
19782
|
-
"kind": "js",
|
|
19783
|
-
"name": "EspalierForm",
|
|
19784
|
-
"declaration": {
|
|
19785
|
-
"name": "EspalierForm",
|
|
19786
|
-
"module": "dist/form/esp-form.js"
|
|
19787
|
-
}
|
|
19788
|
-
},
|
|
19789
|
-
{
|
|
19790
|
-
"kind": "custom-element-definition",
|
|
19791
|
-
"name": "esp-form",
|
|
19792
|
-
"declaration": {
|
|
19793
|
-
"name": "EspalierForm",
|
|
19794
|
-
"module": "dist/form/esp-form.js"
|
|
19795
|
-
}
|
|
19796
|
-
}
|
|
19797
|
-
]
|
|
19798
|
-
},
|
|
19799
19437
|
{
|
|
19800
19438
|
"kind": "javascript-module",
|
|
19801
19439
|
"path": "dist/footer/esp-footer-column.js",
|
|
@@ -22241,6 +21879,368 @@
|
|
|
22241
21879
|
}
|
|
22242
21880
|
]
|
|
22243
21881
|
},
|
|
21882
|
+
{
|
|
21883
|
+
"kind": "javascript-module",
|
|
21884
|
+
"path": "dist/form/esp-form.js",
|
|
21885
|
+
"declarations": [
|
|
21886
|
+
{
|
|
21887
|
+
"kind": "class",
|
|
21888
|
+
"description": "A form wrapper that renders a native `<form>` element in\nthe light DOM. All form-associated custom elements placed\ninside participate natively in form submission, validation,\nand reset.\n\n`esp-form` has no visual presentation of its own — all\nstyling, labels, and layout should be handled independently\n(e.g. via [esp-form-item](/components/form-item), `esp-box`,\nor plain CSS).\n\n### Standard submission\n\n```html\n<esp-form action=\"/api/save\" method=\"post\" label=\"Contact form\">\n <esp-form-item label=\"Name\">\n <esp-input name=\"name\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Send\"></esp-button>\n</esp-form>\n```\n\n### Fetch submission\n\n```html\n<esp-form action=\"/api/save\" use-fetch use-json label=\"Settings\">\n <esp-form-item label=\"Email\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Save\"></esp-button>\n</esp-form>\n```\n\n### Dialog integration\n\nWhen `method=\"dialog\"`, submitting the form dispatches a\n`closeDialog` event that `esp-dialog` listens for, closing\nthe dialog without a network request.\n\n### Multi-field form with validation\n\nRequired fields are validated on submit. The first invalid\nfield is scrolled into view and focused. Errors clear as\nthe user corrects each field. Use the `required-message`\nattribute on any form control to customize the error text.\n\n```html\n<style>\nesp-form.signup-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.signup-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"signup-demo\" use-fetch use-json action=\"/api/signup\" label=\"Sign up\">\n <esp-form-item label=\"Full name\">\n <esp-input name=\"fullName\" required required-message=\"We need your full name.\"></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Email address\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Password\">\n <esp-input name=\"password\" input-type=\"password\" required required-message=\"You must enter a password to continue!\"></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Favorite color\">\n <esp-pick-one name=\"color\" required placeholder=\"Pick one...\" required-message=\"Please choose your favorite color.\">\n <esp-picker-item text=\"Red\" value=\"red\"></esp-picker-item>\n <esp-picker-item text=\"Green\" value=\"green\"></esp-picker-item>\n <esp-picker-item text=\"Blue\" value=\"blue\"></esp-picker-item>\n </esp-pick-one>\n </esp-form-item>\n <esp-form-item label=\"I agree to the terms\">\n <esp-checkbox name=\"terms\" value=\"agreed\" required required-message=\"You must accept the terms to continue.\">\n Yes, I accept\n </esp-checkbox>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Sign Up\"></esp-button>\n <esp-button button-type=\"reset\" label=\"Reset\" variant=\"danger\"></esp-button>\n </div>\n</esp-form>\n```\n\n### Skipping validation\n\nAdd `formnovalidate` to a submit button to bypass constraint\nvalidation. This is useful for \"Save Draft\" buttons that\nshould persist incomplete data.\n\n```html\n<style>\nesp-form.draft-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.draft-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"draft-demo\" use-fetch use-json action=\"/api/drafts\" label=\"Article editor\">\n <esp-form-item label=\"Title\">\n <esp-input name=\"title\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Category\">\n <esp-pick-one name=\"category\" required placeholder=\"Select...\">\n <esp-picker-item text=\"Technology\" value=\"tech\"></esp-picker-item>\n <esp-picker-item text=\"Design\" value=\"design\"></esp-picker-item>\n <esp-picker-item text=\"Business\" value=\"biz\"></esp-picker-item>\n </esp-pick-one>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Publish\"></esp-button>\n <esp-button button-type=\"submit\" formnovalidate label=\"Save Draft\" variant=\"split-complementary-left\"></esp-button>\n </div>\n</esp-form>\n```\n\n### Handling the response\n\nListen for `esp-submit-response` and `esp-submit-error` to\nreact to the server's reply when using fetch submission.\n\n```html\n<style>\nesp-form.response-demo { display: grid; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"response-demo\" use-fetch use-json action=\"/api/feedback\" label=\"Feedback\">\n <esp-form-item label=\"Your feedback\">\n <esp-input name=\"message\" required></esp-input>\n </esp-form-item>\n <esp-button button-type=\"submit\" label=\"Send Feedback\"></esp-button>\n <esp-info id=\"response-msg\" icon=\"info-i\" style=\"display:none\">\n <span id=\"response-text\"></span>\n </esp-info>\n</esp-form>\n<script>\n const form = findByTagName(\"esp-form\")[0];\n const msg = findById(\"response-msg\");\n const text = findById(\"response-text\");\n form.addEventListener(\"esp-submit-response\", (ev) => {\n msg.style.display = \"\";\n msg.setAttribute(\"variant\", ev.detail.ok ? \"success\" : \"warning\");\n text.textContent = ev.detail.ok\n ? \"Submitted successfully!\"\n : \"Server returned an error.\";\n });\n form.addEventListener(\"esp-submit-error\", () => {\n msg.style.display = \"\";\n msg.setAttribute(\"variant\", \"danger\");\n text.textContent = \"Network error — please try again.\";\n });\n</script>\n```\n\n### Form with diverse input types\n\nCombines email, telephone, number, and date inputs with\nvalidation and custom messages.\n\n```html\n<style>\nesp-form.diverse-demo { display: grid; gap: var(--esp-size-small); }\nesp-form.diverse-demo .actions { display: flex; gap: var(--esp-size-small); }\n</style>\n<esp-form class=\"diverse-demo\" use-fetch use-json action=\"/api/contact\" label=\"Contact info\">\n <esp-form-item label=\"Email\">\n <esp-input name=\"email\" input-type=\"email\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Phone\">\n <esp-input name=\"phone\" input-type=\"tel\"\n tel-localities=\"US CA GB\" required>\n </esp-input>\n </esp-form-item>\n <esp-form-item label=\"Age\">\n <esp-input name=\"age\" input-type=\"number\"\n min=\"0\" max=\"150\" required>\n </esp-input>\n </esp-form-item>\n <esp-form-item label=\"Date of birth\">\n <esp-input name=\"dob\" input-type=\"date\" required></esp-input>\n </esp-form-item>\n <esp-form-item label=\"Comments\">\n <esp-textarea name=\"comments\" rows=\"3\"\n placeholder=\"Any additional comments...\">\n </esp-textarea>\n </esp-form-item>\n <div class=\"actions\">\n <esp-button button-type=\"submit\" label=\"Submit\"></esp-button>\n <esp-button button-type=\"reset\" label=\"Reset\" variant=\"danger\"></esp-button>\n </div>\n</esp-form>\n```",
|
|
21889
|
+
"name": "EspalierForm",
|
|
21890
|
+
"members": [
|
|
21891
|
+
{
|
|
21892
|
+
"kind": "field",
|
|
21893
|
+
"name": "_form",
|
|
21894
|
+
"type": {
|
|
21895
|
+
"text": "HTMLFormElement"
|
|
21896
|
+
},
|
|
21897
|
+
"privacy": "private"
|
|
21898
|
+
},
|
|
21899
|
+
{
|
|
21900
|
+
"kind": "field",
|
|
21901
|
+
"name": "_formReady",
|
|
21902
|
+
"type": {
|
|
21903
|
+
"text": "boolean"
|
|
21904
|
+
},
|
|
21905
|
+
"privacy": "private",
|
|
21906
|
+
"default": "false"
|
|
21907
|
+
},
|
|
21908
|
+
{
|
|
21909
|
+
"kind": "field",
|
|
21910
|
+
"name": "action",
|
|
21911
|
+
"type": {
|
|
21912
|
+
"text": "string"
|
|
21913
|
+
},
|
|
21914
|
+
"privacy": "public",
|
|
21915
|
+
"default": "\"\"",
|
|
21916
|
+
"description": "The URL that processes the form submission. When `use-fetch`\nis true this is the URL `fetch()` sends the request to.",
|
|
21917
|
+
"attribute": "action"
|
|
21918
|
+
},
|
|
21919
|
+
{
|
|
21920
|
+
"kind": "field",
|
|
21921
|
+
"name": "method",
|
|
21922
|
+
"type": {
|
|
21923
|
+
"text": "string"
|
|
21924
|
+
},
|
|
21925
|
+
"privacy": "public",
|
|
21926
|
+
"default": "\"post\"",
|
|
21927
|
+
"description": "The HTTP method for submission. Standard values are `get`,\n`post`, and `dialog`. When set to `dialog`, submitting the\nform closes the nearest `esp-dialog` ancestor without making\na network request.",
|
|
21928
|
+
"attribute": "method"
|
|
21929
|
+
},
|
|
21930
|
+
{
|
|
21931
|
+
"kind": "field",
|
|
21932
|
+
"name": "novalidate",
|
|
21933
|
+
"type": {
|
|
21934
|
+
"text": "boolean"
|
|
21935
|
+
},
|
|
21936
|
+
"privacy": "public",
|
|
21937
|
+
"default": "false",
|
|
21938
|
+
"description": "When true, constraint validation is skipped during\nsubmission.",
|
|
21939
|
+
"attribute": "novalidate"
|
|
21940
|
+
},
|
|
21941
|
+
{
|
|
21942
|
+
"kind": "field",
|
|
21943
|
+
"name": "useFetch",
|
|
21944
|
+
"type": {
|
|
21945
|
+
"text": "boolean"
|
|
21946
|
+
},
|
|
21947
|
+
"privacy": "public",
|
|
21948
|
+
"default": "false",
|
|
21949
|
+
"description": "When true, the form uses `fetch()` instead of native\nbrowser navigation for submission. An `esp-submit` event\nis fired with the `FormData` in the detail, allowing\nconsumers to cancel or modify the request.",
|
|
21950
|
+
"attribute": "use-fetch"
|
|
21951
|
+
},
|
|
21952
|
+
{
|
|
21953
|
+
"kind": "field",
|
|
21954
|
+
"name": "useJson",
|
|
21955
|
+
"type": {
|
|
21956
|
+
"text": "boolean"
|
|
21957
|
+
},
|
|
21958
|
+
"privacy": "public",
|
|
21959
|
+
"default": "false",
|
|
21960
|
+
"description": "When `use-fetch` is true and this is also true, the request\nbody is serialized as JSON instead of `FormData`.",
|
|
21961
|
+
"attribute": "use-json"
|
|
21962
|
+
},
|
|
21963
|
+
{
|
|
21964
|
+
"kind": "field",
|
|
21965
|
+
"name": "enctype",
|
|
21966
|
+
"type": {
|
|
21967
|
+
"text": "string"
|
|
21968
|
+
},
|
|
21969
|
+
"privacy": "public",
|
|
21970
|
+
"default": "\"application/x-www-form-urlencoded\"",
|
|
21971
|
+
"description": "The encoding type for form submission. Maps to the native\n`enctype` attribute on the inner `<form>`.",
|
|
21972
|
+
"attribute": "enctype"
|
|
21973
|
+
},
|
|
21974
|
+
{
|
|
21975
|
+
"kind": "field",
|
|
21976
|
+
"name": "label",
|
|
21977
|
+
"type": {
|
|
21978
|
+
"text": "string"
|
|
21979
|
+
},
|
|
21980
|
+
"privacy": "public",
|
|
21981
|
+
"default": "\"\"",
|
|
21982
|
+
"description": "An accessible label applied as `aria-label` on the inner\n`<form>` element so the form is discoverable as an ARIA\n`form` landmark by screen readers.",
|
|
21983
|
+
"attribute": "label"
|
|
21984
|
+
},
|
|
21985
|
+
{
|
|
21986
|
+
"kind": "method",
|
|
21987
|
+
"name": "syncFormAttributes",
|
|
21988
|
+
"privacy": "private",
|
|
21989
|
+
"return": {
|
|
21990
|
+
"type": {
|
|
21991
|
+
"text": "void"
|
|
21992
|
+
}
|
|
21993
|
+
}
|
|
21994
|
+
},
|
|
21995
|
+
{
|
|
21996
|
+
"kind": "method",
|
|
21997
|
+
"name": "checkValidity",
|
|
21998
|
+
"privacy": "public",
|
|
21999
|
+
"return": {
|
|
22000
|
+
"type": {
|
|
22001
|
+
"text": "boolean"
|
|
22002
|
+
}
|
|
22003
|
+
},
|
|
22004
|
+
"description": "Run constraint validation on all controls without showing\nany UI feedback."
|
|
22005
|
+
},
|
|
22006
|
+
{
|
|
22007
|
+
"kind": "method",
|
|
22008
|
+
"name": "reportValidity",
|
|
22009
|
+
"privacy": "public",
|
|
22010
|
+
"return": {
|
|
22011
|
+
"type": {
|
|
22012
|
+
"text": ""
|
|
22013
|
+
}
|
|
22014
|
+
},
|
|
22015
|
+
"description": "Run constraint validation, display error messages via each\ncontrol's `esp-form-item`, and scroll the first invalid\nitem into view."
|
|
22016
|
+
},
|
|
22017
|
+
{
|
|
22018
|
+
"kind": "method",
|
|
22019
|
+
"name": "reset",
|
|
22020
|
+
"privacy": "public",
|
|
22021
|
+
"return": {
|
|
22022
|
+
"type": {
|
|
22023
|
+
"text": "void"
|
|
22024
|
+
}
|
|
22025
|
+
},
|
|
22026
|
+
"description": "Programmatically reset the form and all its controls."
|
|
22027
|
+
},
|
|
22028
|
+
{
|
|
22029
|
+
"kind": "method",
|
|
22030
|
+
"name": "submit",
|
|
22031
|
+
"privacy": "public",
|
|
22032
|
+
"return": {
|
|
22033
|
+
"type": {
|
|
22034
|
+
"text": "void"
|
|
22035
|
+
}
|
|
22036
|
+
},
|
|
22037
|
+
"description": "Programmatically trigger form submission (with validation)."
|
|
22038
|
+
},
|
|
22039
|
+
{
|
|
22040
|
+
"kind": "method",
|
|
22041
|
+
"name": "handleSubmit",
|
|
22042
|
+
"privacy": "private",
|
|
22043
|
+
"return": {
|
|
22044
|
+
"type": {
|
|
22045
|
+
"text": "void"
|
|
22046
|
+
}
|
|
22047
|
+
},
|
|
22048
|
+
"parameters": [
|
|
22049
|
+
{
|
|
22050
|
+
"name": "ev",
|
|
22051
|
+
"type": {
|
|
22052
|
+
"text": "SubmitEvent"
|
|
22053
|
+
}
|
|
22054
|
+
}
|
|
22055
|
+
]
|
|
22056
|
+
},
|
|
22057
|
+
{
|
|
22058
|
+
"kind": "method",
|
|
22059
|
+
"name": "handleKeyDown",
|
|
22060
|
+
"privacy": "private",
|
|
22061
|
+
"return": {
|
|
22062
|
+
"type": {
|
|
22063
|
+
"text": "void"
|
|
22064
|
+
}
|
|
22065
|
+
},
|
|
22066
|
+
"parameters": [
|
|
22067
|
+
{
|
|
22068
|
+
"name": "ev",
|
|
22069
|
+
"type": {
|
|
22070
|
+
"text": "KeyboardEvent"
|
|
22071
|
+
}
|
|
22072
|
+
}
|
|
22073
|
+
]
|
|
22074
|
+
},
|
|
22075
|
+
{
|
|
22076
|
+
"kind": "method",
|
|
22077
|
+
"name": "submitViaFetch",
|
|
22078
|
+
"privacy": "private",
|
|
22079
|
+
"return": {
|
|
22080
|
+
"type": {
|
|
22081
|
+
"text": "Promise<void>"
|
|
22082
|
+
}
|
|
22083
|
+
},
|
|
22084
|
+
"parameters": [
|
|
22085
|
+
{
|
|
22086
|
+
"name": "form",
|
|
22087
|
+
"type": {
|
|
22088
|
+
"text": "HTMLFormElement"
|
|
22089
|
+
}
|
|
22090
|
+
}
|
|
22091
|
+
]
|
|
22092
|
+
},
|
|
22093
|
+
{
|
|
22094
|
+
"kind": "field",
|
|
22095
|
+
"name": "noValidate",
|
|
22096
|
+
"type": {
|
|
22097
|
+
"text": "boolean"
|
|
22098
|
+
},
|
|
22099
|
+
"default": "true"
|
|
22100
|
+
}
|
|
22101
|
+
],
|
|
22102
|
+
"events": [
|
|
22103
|
+
{
|
|
22104
|
+
"name": "closeDialog",
|
|
22105
|
+
"type": {
|
|
22106
|
+
"text": "CustomEvent"
|
|
22107
|
+
},
|
|
22108
|
+
"description": "Fired when `method=\"dialog\"` is used and the form requests its containing `<esp-dialog>` to close. The event detail is an empty object."
|
|
22109
|
+
},
|
|
22110
|
+
{
|
|
22111
|
+
"name": "esp-submit-response",
|
|
22112
|
+
"type": {
|
|
22113
|
+
"text": "CustomEvent<{ response: Response; ok: boolean }>"
|
|
22114
|
+
},
|
|
22115
|
+
"description": "Fired after a successful `fetch` submission."
|
|
22116
|
+
},
|
|
22117
|
+
{
|
|
22118
|
+
"name": "esp-submit-error",
|
|
22119
|
+
"type": {
|
|
22120
|
+
"text": "CustomEvent<{ error: unknown }>"
|
|
22121
|
+
},
|
|
22122
|
+
"description": "Fired when a `fetch` submission fails."
|
|
22123
|
+
},
|
|
22124
|
+
{
|
|
22125
|
+
"type": {
|
|
22126
|
+
"text": "CustomEvent<{ formData: FormData; form: HTMLFormElement }>"
|
|
22127
|
+
},
|
|
22128
|
+
"description": "Fired when `use-fetch` is true and the form passes validation. Cancelable; calling `preventDefault()` aborts the fetch.",
|
|
22129
|
+
"name": "esp-submit"
|
|
22130
|
+
}
|
|
22131
|
+
],
|
|
22132
|
+
"attributes": [
|
|
22133
|
+
{
|
|
22134
|
+
"name": "action",
|
|
22135
|
+
"type": {
|
|
22136
|
+
"text": "string"
|
|
22137
|
+
},
|
|
22138
|
+
"default": "\"\"",
|
|
22139
|
+
"description": "The URL that processes the form submission. When `use-fetch`\nis true this is the URL `fetch()` sends the request to.",
|
|
22140
|
+
"fieldName": "action"
|
|
22141
|
+
},
|
|
22142
|
+
{
|
|
22143
|
+
"name": "method",
|
|
22144
|
+
"type": {
|
|
22145
|
+
"text": "string"
|
|
22146
|
+
},
|
|
22147
|
+
"default": "\"post\"",
|
|
22148
|
+
"description": "The HTTP method for submission. Standard values are `get`,\n`post`, and `dialog`. When set to `dialog`, submitting the\nform closes the nearest `esp-dialog` ancestor without making\na network request.",
|
|
22149
|
+
"fieldName": "method"
|
|
22150
|
+
},
|
|
22151
|
+
{
|
|
22152
|
+
"name": "novalidate",
|
|
22153
|
+
"type": {
|
|
22154
|
+
"text": "boolean"
|
|
22155
|
+
},
|
|
22156
|
+
"default": "false",
|
|
22157
|
+
"description": "When true, constraint validation is skipped during\nsubmission.",
|
|
22158
|
+
"fieldName": "novalidate"
|
|
22159
|
+
},
|
|
22160
|
+
{
|
|
22161
|
+
"name": "use-fetch",
|
|
22162
|
+
"type": {
|
|
22163
|
+
"text": "boolean"
|
|
22164
|
+
},
|
|
22165
|
+
"default": "false",
|
|
22166
|
+
"description": "When true, the form uses `fetch()` instead of native\nbrowser navigation for submission. An `esp-submit` event\nis fired with the `FormData` in the detail, allowing\nconsumers to cancel or modify the request.",
|
|
22167
|
+
"fieldName": "useFetch"
|
|
22168
|
+
},
|
|
22169
|
+
{
|
|
22170
|
+
"name": "use-json",
|
|
22171
|
+
"type": {
|
|
22172
|
+
"text": "boolean"
|
|
22173
|
+
},
|
|
22174
|
+
"default": "false",
|
|
22175
|
+
"description": "When `use-fetch` is true and this is also true, the request\nbody is serialized as JSON instead of `FormData`.",
|
|
22176
|
+
"fieldName": "useJson"
|
|
22177
|
+
},
|
|
22178
|
+
{
|
|
22179
|
+
"name": "enctype",
|
|
22180
|
+
"type": {
|
|
22181
|
+
"text": "string"
|
|
22182
|
+
},
|
|
22183
|
+
"default": "\"application/x-www-form-urlencoded\"",
|
|
22184
|
+
"description": "The encoding type for form submission. Maps to the native\n`enctype` attribute on the inner `<form>`.",
|
|
22185
|
+
"fieldName": "enctype"
|
|
22186
|
+
},
|
|
22187
|
+
{
|
|
22188
|
+
"name": "label",
|
|
22189
|
+
"type": {
|
|
22190
|
+
"text": "string"
|
|
22191
|
+
},
|
|
22192
|
+
"default": "\"\"",
|
|
22193
|
+
"description": "An accessible label applied as `aria-label` on the inner\n`<form>` element so the form is discoverable as an ARIA\n`form` landmark by screen readers.",
|
|
22194
|
+
"fieldName": "label"
|
|
22195
|
+
}
|
|
22196
|
+
],
|
|
22197
|
+
"superclass": {
|
|
22198
|
+
"name": "LitElement",
|
|
22199
|
+
"package": "lit"
|
|
22200
|
+
},
|
|
22201
|
+
"tagName": "esp-form",
|
|
22202
|
+
"customElement": true,
|
|
22203
|
+
"docPageTitle": {
|
|
22204
|
+
"name": "Form",
|
|
22205
|
+
"description": ""
|
|
22206
|
+
},
|
|
22207
|
+
"docUrl": {
|
|
22208
|
+
"name": "/components/form",
|
|
22209
|
+
"description": ""
|
|
22210
|
+
},
|
|
22211
|
+
"menuGroup": {
|
|
22212
|
+
"name": "Form",
|
|
22213
|
+
"description": "Controls"
|
|
22214
|
+
},
|
|
22215
|
+
"menuLabel": {
|
|
22216
|
+
"name": "Form",
|
|
22217
|
+
"description": ""
|
|
22218
|
+
},
|
|
22219
|
+
"menuIcon": {
|
|
22220
|
+
"name": "forms",
|
|
22221
|
+
"description": ""
|
|
22222
|
+
}
|
|
22223
|
+
}
|
|
22224
|
+
],
|
|
22225
|
+
"exports": [
|
|
22226
|
+
{
|
|
22227
|
+
"kind": "js",
|
|
22228
|
+
"name": "EspalierForm",
|
|
22229
|
+
"declaration": {
|
|
22230
|
+
"name": "EspalierForm",
|
|
22231
|
+
"module": "dist/form/esp-form.js"
|
|
22232
|
+
}
|
|
22233
|
+
},
|
|
22234
|
+
{
|
|
22235
|
+
"kind": "custom-element-definition",
|
|
22236
|
+
"name": "esp-form",
|
|
22237
|
+
"declaration": {
|
|
22238
|
+
"name": "EspalierForm",
|
|
22239
|
+
"module": "dist/form/esp-form.js"
|
|
22240
|
+
}
|
|
22241
|
+
}
|
|
22242
|
+
]
|
|
22243
|
+
},
|
|
22244
22244
|
{
|
|
22245
22245
|
"kind": "javascript-module",
|
|
22246
22246
|
"path": "dist/form-item/esp-form-item.js",
|
|
@@ -55382,7 +55382,7 @@
|
|
|
55382
55382
|
}
|
|
55383
55383
|
}
|
|
55384
55384
|
],
|
|
55385
|
-
"description": "Parse an OKLCH CSS string into its components.\n\nAccepts:\n- `
|
|
55385
|
+
"description": "Parse an OKLCH CSS string into its components.\n\nAccepts the CSS Color 4 grammar for the three components:\n- lightness as a number (`0.7`) or percentage (`70%`), clamped to 0–1\n- chroma as a number (`0.125`) or percentage of the 0.4 reference\n maximum (`31.25%` = 0.125), negative values clamped to 0\n- hue as a number or angle (`deg`, `grad`, `rad`, `turn`), signed and\n wrapped into 0–360\n\nAlpha is not supported. Returns `null` if the string is not valid OKLCH."
|
|
55386
55386
|
},
|
|
55387
55387
|
{
|
|
55388
55388
|
"kind": "function",
|
|
@@ -55667,6 +55667,33 @@
|
|
|
55667
55667
|
}
|
|
55668
55668
|
],
|
|
55669
55669
|
"description": "Derive a semantic color with automatic APCA contrast\nenforcement against a reference background."
|
|
55670
|
+
},
|
|
55671
|
+
{
|
|
55672
|
+
"kind": "variable",
|
|
55673
|
+
"name": "ACCEPTED_COLOR_FORMS",
|
|
55674
|
+
"type": {
|
|
55675
|
+
"text": "string"
|
|
55676
|
+
},
|
|
55677
|
+
"default": "'\"#rrggbb\", \"#rgb\", \"rgb(…)\", \"hsl(…)\", \"oklch(…)\"'",
|
|
55678
|
+
"description": "The color forms parseCssColor accepts, for validation\nerror messages and documentation."
|
|
55679
|
+
},
|
|
55680
|
+
{
|
|
55681
|
+
"kind": "function",
|
|
55682
|
+
"name": "parseCssColor",
|
|
55683
|
+
"return": {
|
|
55684
|
+
"type": {
|
|
55685
|
+
"text": "OklchColor | null"
|
|
55686
|
+
}
|
|
55687
|
+
},
|
|
55688
|
+
"parameters": [
|
|
55689
|
+
{
|
|
55690
|
+
"name": "colorStr",
|
|
55691
|
+
"type": {
|
|
55692
|
+
"text": "string"
|
|
55693
|
+
}
|
|
55694
|
+
}
|
|
55695
|
+
],
|
|
55696
|
+
"description": "Parse any accepted CSS color form into OKLCH components.\n\nAccepted forms:\n- `oklch(0.7 0.125 216)` / `oklch(70% 31.25% 0.6turn)` — parsed\n natively via parseOklch, no re-rounding\n- `#rrggbb` / `#rgb`\n- `rgb(120, 72, 106)` / `rgb(120 72 106)` — numbers (with exponents)\n or percentages; the legacy comma syntax requires all channels to be\n the same type, the modern syntax may mix; `rgba()` is accepted as an\n alias of the three-argument form\n- `hsl(338, 25%, 38%)` / `hsl(.94turn 25% 38%)` — hue as a number or\n `deg`/`grad`/`rad`/`turn` angle; the legacy comma syntax requires\n percentage saturation and lightness, the modern syntax also accepts\n bare numbers; `hsla()` is accepted as an alias\n\nCSS comments are equivalent to whitespace in every form, and only\nCSS whitespace (tab, newline, form feed, carriage return, space)\nseparates arguments — JavaScript-only whitespace such as NBSP is\nrejected, matching browsers.\n\nNon-OKLCH forms convert through the forward sRGB → OKLab transform,\nnormalized to display precision (L 3 / C 4 / H 1 decimals, hue 0 when\nachromatic) when that rounding reproduces the identical 8-bit color\nin-gamut, and kept at full precision otherwise. Alpha is rejected in\nevery form — theme colors are opaque.\n\nReturns `null` when the string is not a valid instance of any\naccepted form."
|
|
55670
55697
|
}
|
|
55671
55698
|
],
|
|
55672
55699
|
"exports": [
|
|
@@ -55757,6 +55784,22 @@
|
|
|
55757
55784
|
"name": "deriveSemanticWithContrast",
|
|
55758
55785
|
"module": "dist/shared/color-engine.js"
|
|
55759
55786
|
}
|
|
55787
|
+
},
|
|
55788
|
+
{
|
|
55789
|
+
"kind": "js",
|
|
55790
|
+
"name": "ACCEPTED_COLOR_FORMS",
|
|
55791
|
+
"declaration": {
|
|
55792
|
+
"name": "ACCEPTED_COLOR_FORMS",
|
|
55793
|
+
"module": "dist/shared/color-engine.js"
|
|
55794
|
+
}
|
|
55795
|
+
},
|
|
55796
|
+
{
|
|
55797
|
+
"kind": "js",
|
|
55798
|
+
"name": "parseCssColor",
|
|
55799
|
+
"declaration": {
|
|
55800
|
+
"name": "parseCssColor",
|
|
55801
|
+
"module": "dist/shared/color-engine.js"
|
|
55802
|
+
}
|
|
55760
55803
|
}
|
|
55761
55804
|
]
|
|
55762
55805
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{parseCssColor as y,serializeOklch as p,gamutMapToSRGB as S,deriveSemantic as v,deriveSemanticWithContrast as B}from"../../shared/color-engine.js";import{generateScaleProperties as C}from"../../shared/scale-engine.js";import{SEMANTIC_COLOR_NAMES as l,LIGHTNESS_KEYS as x,semanticToCSS as b}from"../../shared/theme.js";import{lightnessKeyToCSS as I}from"./lightness-key-to-css.js";import{computeVariants as M}from"./compute-variants.js";function O(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function W(o,k){const d=y(o.seedColor);if(!d)return{};const n={};n["--esp-scheme"]=k,n["--esp-seed-color"]=o.seedColor;const c=M(d,o);for(const[a,t]of Object.entries(c))n[`--esp-color-${a}`]=p(S(t));for(const a of x)n[I(a)]=`${Math.round(o.lightness[a]*100)}%`;const u={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},s={};for(const a of l){if(u[a])continue;const t=o.semanticMappings[a],i=o.chroma[a],r=c[t.source],e=o.lightness[t.lightness],g=v(r,e,i.min,i.max);s[a]=g,n[b(a)]=p(g)}for(const a of l){const t=u[a];if(!t)continue;const i=o.semanticMappings[a],r=o.chroma[a],e=c[i.source],g=o.lightness[i.lightness],m=s[t.bg],f=B(e,g,r.min,r.max,m,t.targetLc);s[a]=f,n[b(a)]=p(f)}return Object.assign(n,C(O(o))),o.fontBody&&(n["--esp-font-body"]=o.fontBody),o.fontHeadings&&(n["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(n["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(n["--esp-font-monospace"]=o.fontMonospace),n["--esp-font-weight-body"]=o.fontWeightBody,n["--esp-font-weight-headings"]=o.fontWeightHeadings,n["--esp-font-weight-brand"]=o.fontWeightBrand,n["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(n["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(n["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(n["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(n["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(n["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(n["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(n["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),n}export{W as computeThemeProperties};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const S=Math.PI/180,
|
|
1
|
+
const S=Math.PI/180,h=1e-4,$=50,m="[+-]?(?:\\d+|\\d*\\.\\d+)(?:[eE][+-]?\\d+)?",i="[\\t\\n\\f\\r ]",X=new RegExp(i+"*,"+i+"*"),y=new RegExp(i+"+");function G(t){return t.replace(/\/\*[\s\S]*?(?:\*\/|$)/g," ").replace(/^[\t\n\f\r ]+|[\t\n\f\r ]+$/g,"")}const L={"":1,deg:1,grad:.9,rad:180/Math.PI,turn:360},H=.4,U=new RegExp("^oklch\\("+i+"*("+m+")(%?)"+i+"+("+m+")(%?)"+i+"+("+m+")(deg|grad|rad|turn)?"+i+"*\\)$","i");function V(t){const n=t.h*S;return{L:t.l,a:t.c*Math.cos(n),b:t.c*Math.sin(n)}}function W(t){const n=t.L+.3963377774*t.a+.2158037573*t.b,r=t.L-.1055613458*t.a-.0638541728*t.b,e=t.L-.0894841775*t.a-1.291485548*t.b,o=n*n*n,u=r*r*r,c=e*e*e;return{r:4.0767416621*o-3.3077115913*u+.2309699292*c,g:-1.2684380046*o+2.6097574011*u-.3413193965*c,b:-.0041960863*o-.7034186147*u+1.707614701*c}}function T(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function z(t){return{r:T(t.r),g:T(t.g),b:T(t.b)}}function Y(t){return t.r>=-h&&t.r<=1+h&&t.g>=-h&&t.g<=1+h&&t.b>=-h&&t.b<=1+h}function g(t){return Math.max(0,Math.min(1,t))}function q(t){const n=G(t).match(U);if(!n)return null;let r=parseFloat(n[1]);n[2]==="%"&&(r/=100);let e=parseFloat(n[3]);n[4]==="%"&&(e=e/100*H);const o=parseFloat(n[5])*L[(n[6]??"").toLowerCase()];return!isFinite(r)||!isFinite(e)||!isFinite(o)?null:{l:Math.max(0,Math.min(1,r)),c:Math.max(0,e),h:(o%360+360)%360}}function ct(t){const n=p(t.l,6),r=p(t.c,6),e=p((t.h%360+360)%360,4);return`oklch(${n} ${r} ${e})`}function _(t){return z(W(V(t)))}function x(t){return Y(_(t))}function M(t){if(t.c<=h||x(t))return{...t};let n=0,r=t.c,e={...t};for(let o=0;o<$;o++){const u=(n+r)/2;if(e={l:t.l,c:u,h:t.h},x(e)?n=u:r=u,r-n<h)break}return{l:t.l,c:n,h:t.h}}function K(t,n,r){const e={l:t.l,c:Math.max(n,Math.min(r,t.c)),h:t.h};return M(e)}const C=.022,w=.012,O=.022,b=.57,k=.56,P=1.14,A=.001,R=.027;function B(t){const n=Math.pow(g(t.r),2.4),r=Math.pow(g(t.g),2.4),e=Math.pow(g(t.b),2.4);return .2126729*n+.7151522*r+.072175*e}function I(t,n){const r=_(M(t)),e=_(M(n));let o=B(r),u=B(e);if(o=o>C?o:o+Math.pow(C-o,1.414),u=u>C?u:u+Math.pow(C-u,1.414),Math.abs(u-o)<A)return 0;let c;if(u>o){const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c<A)return 0;c=c<R?c-c*O*R:c-O}else{const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c>-A)return 0;c=c>-R?c-c*w*R:c+w}return c*100}function j(t,n,r=60){let e=M({...t}),o=Math.abs(I(e,n));if(o>=r)return e;const u=n.l>.5,c=.01,s=u?0:1;for(let a=0;a<100;a++){if(u?e.l=Math.max(s,e.l-c):e.l=Math.min(s,e.l+c),e=M(e),o=Math.abs(I(e,n)),o>=r)return e;if(e.l<=0||e.l>=1)break}return e}function st(t,n){return((t+n)%360+360)%360}function J(t,n,r,e){return K({l:n,c:t.c,h:t.h},r,e)}function at(t,n,r,e,o,u=60){const c=J(t,n,r,e);return j(c,o,u)}function E(t){return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Q(t){const n=E(t.r),r=E(t.g),e=E(t.b),o=Math.cbrt(.4122214708*n+.5363325363*r+.0514459929*e),u=Math.cbrt(.2119034982*n+.6806995451*r+.1073969566*e),c=Math.cbrt(.0883024619*n+.2817188376*r+.6299787005*e);return{L:.2104542553*o+.793617785*u-.0040720468*c,a:1.9779984951*o-2.428592205*u+.4505937099*c,b:.0259040371*o+.7827717662*u-.808675766*c}}function Z(t){const n=Math.sqrt(t.a*t.a+t.b*t.b),r=(Math.atan2(t.b,t.a)/S%360+360)%360;return{l:t.L,c:n,h:r}}function tt(t){const n=p(t.c,4);return{l:p(t.l,3),c:n,h:n===0?0:p(t.h,1)}}function f(t){return Math.round(g(t)*255)}function d(t){const n=Z(Q(t)),r=t.r===t.g&&t.g===t.b?{l:n.l,c:0,h:0}:n,e=tt(r);if(x(e)){const o=_(e);if(f(o.r)===f(t.r)&&f(o.g)===f(t.g)&&f(o.b)===f(t.b))return e}return r}function nt(t){const n=t.slice(1);if(!/^[0-9a-f]+$/i.test(n))return null;if(n.length===3){const[r,e,o]=n.split("").map(u=>parseInt(u+u,16));return{r:r/255,g:e/255,b:o/255}}return n.length===6?{r:parseInt(n.slice(0,2),16)/255,g:parseInt(n.slice(2,4),16)/255,b:parseInt(n.slice(4,6),16)/255}:null}function F(t,n){const r=t.match(new RegExp("^"+n+"\\("+i+"*([^)]*?)"+i+"*\\)$","i"));if(!r)return null;const e=r[1];if(e.includes("/"))return null;const o=e.includes(","),u=e.split(o?X:y);return u.length!==3||u.some(c=>c.length===0)?null:{args:u,legacy:o}}const rt=new RegExp("^("+m+")([a-z%]*)$","i");function D(t){const n=t.match(rt);if(!n)return null;const r=parseFloat(n[1]);return isFinite(r)?{value:r,unit:n[2].toLowerCase()}:null}function et(t){if(t.unit!==""&&t.unit!=="%")return null;const n=t.unit==="%"?t.value/100:t.value/255;return Math.max(0,Math.min(1,n))}function ot(t){const n=L[t.unit];return n===void 0?null:t.value*n}function N(t){return t.unit!==""&&t.unit!=="%"?null:Math.max(0,Math.min(1,t.value/100))}function ut(t,n,r){const e=(t%360+360)%360,o=u=>{const c=(u+e/30)%12,s=n*Math.min(r,1-r);return r-s*Math.max(-1,Math.min(c-3,9-c,1))};return{r:o(0),g:o(8),b:o(4)}}const it='"#rrggbb", "#rgb", "rgb(\u2026)", "hsl(\u2026)", "oklch(\u2026)"';function lt(t){const n=G(t);if(n.startsWith("#")){const r=nt(n);return r?d(r):null}if(/^oklch\(/i.test(n))return q(n);if(/^rgba?\(/i.test(n)){const r=F(n,"rgba?");if(!r)return null;const e=r.args.map(D);if(e.some(l=>l===null))return null;const o=e;if(r.legacy&&new Set(o.map(l=>l.unit)).size>1)return null;const u=o.map(et);if(u.some(l=>l===null))return null;const[c,s,a]=u;return d({r:c,g:s,b:a})}if(/^hsla?\(/i.test(n)){const r=F(n,"hsla?");if(!r)return null;const e=r.args.map(D);if(e.some(v=>v===null))return null;const[o,u,c]=e;if(r.legacy&&(u.unit!=="%"||c.unit!=="%"))return null;const s=ot(o),a=N(u),l=N(c);return s===null||a===null||l===null?null:d(ut(s,a,l))}return null}function p(t,n){const r=Math.pow(10,n);return Math.round(t*r)/r}export{it as ACCEPTED_COLOR_FORMS,I as apcaContrast,K as clampChromaAndGamutMap,J as deriveSemantic,at as deriveSemanticWithContrast,j as ensureContrast,M as gamutMapToSRGB,x as isInSRGBGamut,_ as oklchToSRGB,lt as parseCssColor,q as parseOklch,st as rotateHue,ct as serializeOklch};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,o);else for(var c=f.length-1;c>=0;c--)(a=f[c])&&(s=(r<3?a(s):r>3?a(e,t,s):a(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as E,LitElement as x}from"lit";import{property as y,state as U}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as V}from"./utilities.js";import{
|
|
1
|
+
var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,o);else for(var c=f.length-1;c>=0;c--)(a=f[c])&&(s=(r<3?a(s):r>3?a(e,t,s):a(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as E,LitElement as x}from"lit";import{property as y,state as U}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as V}from"./utilities.js";import{parseCssColor as A,serializeOklch as k,gamutMapToSRGB as L,deriveSemantic as O,deriveSemanticWithContrast as F}from"./color-engine.js";import{computeVariants as T}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as S,semanticToCSS as P}from"./theme.js";import{alignAttributeTextInheritance as _,focusRing as z}from"./style-fragments.js";class n extends x{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.variantTokenOriginalValues=new Map,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.variantBacker="primary",this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyVariantTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyVariantTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyVariantTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const o=()=>{const r=e();return r?(r.focus(t),!0):!1};o()||this.updateComplete.then(()=>{o()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get variant(){return this.variantBacker}set variant(e){this.variantBacker=e,this.applyVariantTokens()}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0)}syncRootFromDom(e){const t=V(this,"esp-root");if(!t){if(this.espRoot&&this.clearVariantTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const o=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,c=this.seedColor!==t.seedColor;return this.espRoot=t,o&&this.isConnected&&this.subscribeToRootEvents(t),(o||a||c)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyVariantTokens()),o&&this.requestUpdate(),t}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[g(e,"seed-color-changed",this.handleSeedColorChanged),g(e,"scheme-changed",this.handleSchemeChanged),g(e,"theme-changed",this.handleThemeChanged),g(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return V(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=A(t.seedColor);if(!o)return;const s=T(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(L(s)));const a=T(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,b={};for(const i of S){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),v=a[d],m=t.lightness[l.lightness],u=O(v,m,h.min,h.max);b[i]=u,this.setVariantTokenProperty(P(i),k(u))}for(const i of S){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],v=this.effectiveVariantTokenSource(i,h.source,c),m=a[v],u=t.lightness[h.lightness],w=b[l.bg],R=F(m,u,d.min,d.max,w,l.targetLc);b[i]=R,this.setVariantTokenProperty(P(i),k(R))}}effectiveVariantTokenSource(e,t,o){return o&&n.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}setVariantTokenProperty(e,t){const o=this.variantTokenOriginalValues.get(e);if(o){const r=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(r!==o.generatedValue||s!==o.generatedPriority)&&(o.originalValue=r.length?r:null,o.originalPriority=s),o.generatedValue=t,o.generatedPriority=""}else{const r=this.style.getPropertyValue(e);this.variantTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:r.length?r:null})}this.style.setProperty(e,t)}clearVariantTokens(){for(const[e,t]of this.variantTokenOriginalValues){const o=this.style.getPropertyValue(e),r=this.style.getPropertyPriority(e);(o!==t.generatedValue||r!==t.generatedPriority)&&(t.originalValue=o.length?o:null,t.originalPriority=r),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority)}this.variantTokenOriginalValues.clear()}}n.textContrast={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[z(".esp-field:focus-within","--esp-field-focus-shadow"),_,E`
|
|
2
2
|
:host {
|
|
3
3
|
|
|
4
4
|
--_esp-field-resolved-hover-bg: var(
|
package/dist/shared/theme.d.ts
CHANGED
|
@@ -74,7 +74,14 @@ export interface SemanticMapping {
|
|
|
74
74
|
export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
|
|
75
75
|
/** The complete, resolved Espalier theme. */
|
|
76
76
|
export interface EspalierTheme {
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Seed color — drives the entire palette.
|
|
79
|
+
*
|
|
80
|
+
* A theme author may supply any common CSS color form (`#rrggbb`,
|
|
81
|
+
* `#rgb`, `rgb()`, `hsl()`, or `oklch()`); non-OKLCH forms are
|
|
82
|
+
* converted at the merge boundary, so a **resolved** theme always
|
|
83
|
+
* carries an `oklch()` string here.
|
|
84
|
+
*/
|
|
78
85
|
seedColor: string;
|
|
79
86
|
/** CSS `font-family` for body / UI text. */
|
|
80
87
|
fontBody: string;
|
package/dist/shared/theme.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseOklch as O}from"./color-engine.js";const h=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],$=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],C=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],d=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],I={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},T={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},y={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},f=.4;function b(){const i={};for(const e of h)i[e]={min:0,max:f};return i}const B={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90},variantChroma:{},chroma:b(),semanticMappings:{...y}},_={...B,chroma:b(),semanticMappings:{...y},lightness:{...I}},W={...B,chroma:b(),semanticMappings:{...y},lightness:{...T}},M=new Set(["__proto__","constructor","prototype"]);function l(i){return!M.has(i)}function w(i,e){return M.has(i)?void 0:e}function F(i){return`--esp-color-${i.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function R(i){try{const e=atob(i),s=JSON.parse(e,w);return typeof s!="object"||s===null||Array.isArray(s)?null:s}catch{return null}}function k(i){return btoa(JSON.stringify(i))}function N(i,e){const s={...i,seedColor:e.seedColor??i.seedColor,fontBody:e.fontBody??i.fontBody,fontHeadings:e.fontHeadings??i.fontHeadings,fontBrand:e.fontBrand??i.fontBrand,fontMonospace:e.fontMonospace??i.fontMonospace,fontWeightBody:String(e.fontWeightBody??i.fontWeightBody),fontWeightHeadings:String(e.fontWeightHeadings??i.fontWeightHeadings),fontWeightBrand:String(e.fontWeightBrand??i.fontWeightBrand),fontWeightMonospace:String(e.fontWeightMonospace??i.fontWeightMonospace),stylesheets:e.stylesheets??[...i.stylesheets],rootFontSize:e.rootFontSize??i.rootFontSize,typeRatio:e.typeRatio??i.typeRatio,spaceRatio:e.spaceRatio??i.spaceRatio,borderRadius:e.borderRadius??i.borderRadius,viewportMin:e.viewportMin??i.viewportMin,viewportMax:e.viewportMax??i.viewportMax,angles:{...i.angles,...e.angles},semanticHues:{...i.semanticHues,...e.semanticHues},variantChroma:{...i.variantChroma,...e.variantChroma},lightness:{...i.lightness,...e.lightness},chroma:S(i.chroma,e.chroma),semanticMappings:S(i.semanticMappings,e.semanticMappings)};return e.pageBackgroundImage!==void 0&&(s.pageBackgroundImage=e.pageBackgroundImage),e.pageBackgroundImageOpacity!==void 0&&(s.pageBackgroundImageOpacity=e.pageBackgroundImageOpacity),e.boxBackgroundImage!==void 0&&(s.boxBackgroundImage=e.boxBackgroundImage),e.boxBackgroundImageOpacity!==void 0&&(s.boxBackgroundImageOpacity=e.boxBackgroundImageOpacity),e.vellumOpacity!==void 0&&(s.vellumOpacity=e.vellumOpacity),e.vellumBackgroundImage!==void 0&&(s.vellumBackgroundImage=e.vellumBackgroundImage),e.vellumBackgroundImageOpacity!==void 0&&(s.vellumBackgroundImageOpacity=e.vellumBackgroundImageOpacity),s}function S(i,e){if(!e)return{...i};const s={...i};for(const c of Object.keys(e)){const u=e[c];u!==void 0&&(s[c]=u)}return s}function L(i){const e=[],s=[];let c;try{c=atob(i)}catch{return e.push("Failed to decode Base64 string."),{valid:!1,errors:e,warnings:s}}let u;try{u=JSON.parse(c)}catch{return e.push("Decoded string is not valid JSON."),{valid:!1,errors:e,warnings:s}}if(typeof u!="object"||u===null||Array.isArray(u))return e.push("Theme must be a JSON object."),{valid:!1,errors:e,warnings:s};const o=u;"seedColor"in o&&(typeof o.seedColor!="string"?e.push("seedColor must be a string."):O(o.seedColor)||e.push(`seedColor is not a valid OKLCH value: "${o.seedColor}".`));for(const t of["fontBody","fontHeadings","fontBrand","fontMonospace"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);const g=["normal","bold","lighter","bolder"],p=["inherit","initial","unset","revert","revert-layer"];for(const t of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(t in o){const n=o[t];if(typeof n=="number")(n<1||n>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got ${n}).`);else if(typeof n=="string"){const a=g.includes(n)||p.includes(n);if(/^\d+$/.test(n)){const x=Number(n);(x<1||x>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got "${n}").`)}else a||s.push(`${t} = "${n}" is not a standard font-weight value.`)}else e.push(`${t} must be a string or number.`)}"stylesheets"in o&&(Array.isArray(o.stylesheets)?o.stylesheets.some(t=>typeof t!="string")&&e.push("Every entry in stylesheets must be a string."):e.push("stylesheets must be an array of strings."));const m=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[t,n,a]of m)if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const r=o[t];n!==void 0&&r<n&&e.push(`${t} must be \u2265 ${n} (got ${r}).`),a!==void 0&&r>a&&s.push(`${t} = ${r} is unusually high (max ${a}).`)}for(const t of["typeRatio","spaceRatio"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];n<=1&&e.push(`${t} must be > 1 (got ${n}).`);const a=t==="typeRatio"?1.3:2;n>a&&s.push(`${t} = ${n} is very high (max ${a}); scales may be extreme.`)}if("viewportMin"in o&&"viewportMax"in o){const t=o.viewportMin,n=o.viewportMax;typeof t=="number"&&typeof n=="number"&&t>=n&&e.push(`viewportMin (${t}) must be less than viewportMax (${n}).`)}if("angles"in o)if(typeof o.angles!="object"||o.angles===null)e.push("angles must be an object.");else{const t=o.angles;for(const n of["analogous","complementary","splitComplementary","triadic"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`angles.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`angles.${n} = ${a} is outside 0\u2013360.`)}}if("semanticHues"in o)if(typeof o.semanticHues!="object"||o.semanticHues===null)e.push("semanticHues must be an object.");else{const t=o.semanticHues;for(const n of["danger","success","warning"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`semanticHues.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`semanticHues.${n} = ${a} is outside 0\u2013360.`)}}if("variantChroma"in o)if(typeof o.variantChroma!="object"||o.variantChroma===null)e.push("variantChroma must be an object.");else{const t=o.variantChroma;for(const n of C)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`variantChroma["${n}"] must be a finite number.`);else{const a=t[n];a<0&&e.push(`variantChroma["${n}"] must be \u2265 0 (got ${a}).`),a>f&&s.push(`variantChroma["${n}"] = ${a} exceeds ${f}.`)}}if("lightness"in o)if(typeof o.lightness!="object"||o.lightness===null)e.push("lightness must be an object.");else{const t=o.lightness;for(const n of d)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`lightness.${n} must be a finite number.`);else{const a=t[n];(a<0||a>1)&&e.push(`lightness.${n} must be 0\u20131 (got ${a}).`)}}if("chroma"in o)if(typeof o.chroma!="object"||o.chroma===null)e.push("chroma must be an object.");else{const t=o.chroma;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`chroma.${n} must be { min, max }.`);continue}const r=a;(typeof r.min!="number"||r.min<0)&&e.push(`chroma.${n}.min must be \u2265 0.`),(typeof r.max!="number"||r.max<0||r.max>f)&&e.push(`chroma.${n}.max must be 0\u2013${f}.`),typeof r.min=="number"&&typeof r.max=="number"&&r.min>r.max&&e.push(`chroma.${n}.min (${r.min}) must be \u2264 max (${r.max}).`)}}if("semanticMappings"in o)if(typeof o.semanticMappings!="object"||o.semanticMappings===null)e.push("semanticMappings must be an object.");else{const t=o.semanticMappings;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`semanticMappings.${n} must be { source, lightness }.`);continue}const r=a;(typeof r.source!="string"||!$.includes(r.source))&&e.push(`semanticMappings.${n}.source must be one of: ${$.join(", ")}.`),(typeof r.lightness!="string"||!d.includes(r.lightness))&&e.push(`semanticMappings.${n}.lightness must be one of: ${d.join(", ")}.`)}}for(const t of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);for(const t of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];(n<0||n>1)&&e.push(`${t} must be 0\u20131 (got ${n}).`)}return{valid:e.length===0,errors:e,warnings:s}}const A=["angles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function E(i,e){const s={};for(const[c,u]of Object.entries(i))l(c)&&(s[c]=u);for(const[c,u]of Object.entries(e))u!==void 0&&l(c)&&(s[c]=u);for(const c of A){const u=i[c],o=e[c];if(u&&typeof u=="object"&&!Array.isArray(u)&&o&&typeof o=="object"&&!Array.isArray(o)){const g={};for(const[p,m]of Object.entries(u))l(p)&&(g[p]=m);for(const[p,m]of Object.entries(o))m!==void 0&&l(p)&&(g[p]=m);s[c]=g}}return s}function D(...i){let e={};for(const s of i){if(!s)continue;const c=R(s);c&&(e=E(e,c))}return k(e)}function v(i){return i.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const H={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function K(i){return k({...H,pageBackgroundImage:`url("${v(i)}")`,pageBackgroundImageOpacity:.5})}function U(i){return k({...H,pageBackgroundImage:`url("${v(i)}")`,pageBackgroundImageOpacity:.55})}export{$ as COLOR_SOURCES,T as DEFAULT_DARK_LIGHTNESS,W as DEFAULT_DARK_THEME,I as DEFAULT_LIGHT_LIGHTNESS,_ as DEFAULT_LIGHT_THEME,y as DEFAULT_SEMANTIC_MAPPINGS,d as LIGHTNESS_KEYS,A as NESTED_THEME_KEYS,h as SEMANTIC_COLOR_NAMES,C as VARIANT_COLOR_SOURCES,U as buildTaprootDarkTheme,K as buildTaprootLightTheme,k as encodeTheme,D as layerThemes,E as mergePartials,N as mergeTheme,R as parseTheme,F as semanticToCSS,L as validateTheme};
|
|
1
|
+
import{ACCEPTED_COLOR_FORMS as v,parseCssColor as $,parseOklch as I,serializeOklch as T}from"./color-engine.js";const h=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],B=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],R=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],d=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],w={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},A={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},y={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},f=.4;function b(){const i={};for(const e of h)i[e]={min:0,max:f};return i}const M={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90},variantChroma:{},chroma:b(),semanticMappings:{...y}},L={...M,chroma:b(),semanticMappings:{...y},lightness:{...w}},D={...M,chroma:b(),semanticMappings:{...y},lightness:{...A}},S=new Set(["__proto__","constructor","prototype"]);function l(i){return!S.has(i)}function E(i,e){return S.has(i)?void 0:e}function U(i){return`--esp-color-${i.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function _(i){try{const e=atob(i),s=JSON.parse(e,E);return typeof s!="object"||s===null||Array.isArray(s)?null:s}catch{return null}}function k(i){return btoa(JSON.stringify(i))}function j(i){if(I(i))return i;const e=$(i);return e?T(e):i}function K(i,e){const s={...i,seedColor:typeof e.seedColor=="string"?j(e.seedColor):i.seedColor,fontBody:e.fontBody??i.fontBody,fontHeadings:e.fontHeadings??i.fontHeadings,fontBrand:e.fontBrand??i.fontBrand,fontMonospace:e.fontMonospace??i.fontMonospace,fontWeightBody:String(e.fontWeightBody??i.fontWeightBody),fontWeightHeadings:String(e.fontWeightHeadings??i.fontWeightHeadings),fontWeightBrand:String(e.fontWeightBrand??i.fontWeightBrand),fontWeightMonospace:String(e.fontWeightMonospace??i.fontWeightMonospace),stylesheets:e.stylesheets??[...i.stylesheets],rootFontSize:e.rootFontSize??i.rootFontSize,typeRatio:e.typeRatio??i.typeRatio,spaceRatio:e.spaceRatio??i.spaceRatio,borderRadius:e.borderRadius??i.borderRadius,viewportMin:e.viewportMin??i.viewportMin,viewportMax:e.viewportMax??i.viewportMax,angles:{...i.angles,...e.angles},semanticHues:{...i.semanticHues,...e.semanticHues},variantChroma:{...i.variantChroma,...e.variantChroma},lightness:{...i.lightness,...e.lightness},chroma:C(i.chroma,e.chroma),semanticMappings:C(i.semanticMappings,e.semanticMappings)};return e.pageBackgroundImage!==void 0&&(s.pageBackgroundImage=e.pageBackgroundImage),e.pageBackgroundImageOpacity!==void 0&&(s.pageBackgroundImageOpacity=e.pageBackgroundImageOpacity),e.boxBackgroundImage!==void 0&&(s.boxBackgroundImage=e.boxBackgroundImage),e.boxBackgroundImageOpacity!==void 0&&(s.boxBackgroundImageOpacity=e.boxBackgroundImageOpacity),e.vellumOpacity!==void 0&&(s.vellumOpacity=e.vellumOpacity),e.vellumBackgroundImage!==void 0&&(s.vellumBackgroundImage=e.vellumBackgroundImage),e.vellumBackgroundImageOpacity!==void 0&&(s.vellumBackgroundImageOpacity=e.vellumBackgroundImageOpacity),s}function C(i,e){if(!e)return{...i};const s={...i};for(const c of Object.keys(e)){const u=e[c];u!==void 0&&(s[c]=u)}return s}function z(i){const e=[],s=[];let c;try{c=atob(i)}catch{return e.push("Failed to decode Base64 string."),{valid:!1,errors:e,warnings:s}}let u;try{u=JSON.parse(c)}catch{return e.push("Decoded string is not valid JSON."),{valid:!1,errors:e,warnings:s}}if(typeof u!="object"||u===null||Array.isArray(u))return e.push("Theme must be a JSON object."),{valid:!1,errors:e,warnings:s};const o=u;"seedColor"in o&&(typeof o.seedColor!="string"?e.push("seedColor must be a string."):$(o.seedColor)||e.push(`seedColor is not a valid CSS color: "${o.seedColor}". Accepted forms: ${v}.`));for(const t of["fontBody","fontHeadings","fontBrand","fontMonospace"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);const g=["normal","bold","lighter","bolder"],p=["inherit","initial","unset","revert","revert-layer"];for(const t of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(t in o){const n=o[t];if(typeof n=="number")(n<1||n>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got ${n}).`);else if(typeof n=="string"){const a=g.includes(n)||p.includes(n);if(/^\d+$/.test(n)){const x=Number(n);(x<1||x>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got "${n}").`)}else a||s.push(`${t} = "${n}" is not a standard font-weight value.`)}else e.push(`${t} must be a string or number.`)}"stylesheets"in o&&(Array.isArray(o.stylesheets)?o.stylesheets.some(t=>typeof t!="string")&&e.push("Every entry in stylesheets must be a string."):e.push("stylesheets must be an array of strings."));const m=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[t,n,a]of m)if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const r=o[t];n!==void 0&&r<n&&e.push(`${t} must be \u2265 ${n} (got ${r}).`),a!==void 0&&r>a&&s.push(`${t} = ${r} is unusually high (max ${a}).`)}for(const t of["typeRatio","spaceRatio"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];n<=1&&e.push(`${t} must be > 1 (got ${n}).`);const a=t==="typeRatio"?1.3:2;n>a&&s.push(`${t} = ${n} is very high (max ${a}); scales may be extreme.`)}if("viewportMin"in o&&"viewportMax"in o){const t=o.viewportMin,n=o.viewportMax;typeof t=="number"&&typeof n=="number"&&t>=n&&e.push(`viewportMin (${t}) must be less than viewportMax (${n}).`)}if("angles"in o)if(typeof o.angles!="object"||o.angles===null)e.push("angles must be an object.");else{const t=o.angles;for(const n of["analogous","complementary","splitComplementary","triadic"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`angles.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`angles.${n} = ${a} is outside 0\u2013360.`)}}if("semanticHues"in o)if(typeof o.semanticHues!="object"||o.semanticHues===null)e.push("semanticHues must be an object.");else{const t=o.semanticHues;for(const n of["danger","success","warning"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`semanticHues.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`semanticHues.${n} = ${a} is outside 0\u2013360.`)}}if("variantChroma"in o)if(typeof o.variantChroma!="object"||o.variantChroma===null)e.push("variantChroma must be an object.");else{const t=o.variantChroma;for(const n of R)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`variantChroma["${n}"] must be a finite number.`);else{const a=t[n];a<0&&e.push(`variantChroma["${n}"] must be \u2265 0 (got ${a}).`),a>f&&s.push(`variantChroma["${n}"] = ${a} exceeds ${f}.`)}}if("lightness"in o)if(typeof o.lightness!="object"||o.lightness===null)e.push("lightness must be an object.");else{const t=o.lightness;for(const n of d)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`lightness.${n} must be a finite number.`);else{const a=t[n];(a<0||a>1)&&e.push(`lightness.${n} must be 0\u20131 (got ${a}).`)}}if("chroma"in o)if(typeof o.chroma!="object"||o.chroma===null)e.push("chroma must be an object.");else{const t=o.chroma;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`chroma.${n} must be { min, max }.`);continue}const r=a;(typeof r.min!="number"||r.min<0)&&e.push(`chroma.${n}.min must be \u2265 0.`),(typeof r.max!="number"||r.max<0||r.max>f)&&e.push(`chroma.${n}.max must be 0\u2013${f}.`),typeof r.min=="number"&&typeof r.max=="number"&&r.min>r.max&&e.push(`chroma.${n}.min (${r.min}) must be \u2264 max (${r.max}).`)}}if("semanticMappings"in o)if(typeof o.semanticMappings!="object"||o.semanticMappings===null)e.push("semanticMappings must be an object.");else{const t=o.semanticMappings;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`semanticMappings.${n} must be { source, lightness }.`);continue}const r=a;(typeof r.source!="string"||!B.includes(r.source))&&e.push(`semanticMappings.${n}.source must be one of: ${B.join(", ")}.`),(typeof r.lightness!="string"||!d.includes(r.lightness))&&e.push(`semanticMappings.${n}.lightness must be one of: ${d.join(", ")}.`)}}for(const t of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);for(const t of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];(n<0||n>1)&&e.push(`${t} must be 0\u20131 (got ${n}).`)}return{valid:e.length===0,errors:e,warnings:s}}const W=["angles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function F(i,e){const s={};for(const[c,u]of Object.entries(i))l(c)&&(s[c]=u);for(const[c,u]of Object.entries(e))u!==void 0&&l(c)&&(s[c]=u);for(const c of W){const u=i[c],o=e[c];if(u&&typeof u=="object"&&!Array.isArray(u)&&o&&typeof o=="object"&&!Array.isArray(o)){const g={};for(const[p,m]of Object.entries(u))l(p)&&(g[p]=m);for(const[p,m]of Object.entries(o))m!==void 0&&l(p)&&(g[p]=m);s[c]=g}}return s}function G(...i){let e={};for(const s of i){if(!s)continue;const c=_(s);c&&(e=F(e,c))}return k(e)}function O(i){return i.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const H={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function J(i){return k({...H,pageBackgroundImage:`url("${O(i)}")`,pageBackgroundImageOpacity:.5})}function P(i){return k({...H,pageBackgroundImage:`url("${O(i)}")`,pageBackgroundImageOpacity:.55})}export{B as COLOR_SOURCES,A as DEFAULT_DARK_LIGHTNESS,D as DEFAULT_DARK_THEME,w as DEFAULT_LIGHT_LIGHTNESS,L as DEFAULT_LIGHT_THEME,y as DEFAULT_SEMANTIC_MAPPINGS,d as LIGHTNESS_KEYS,W as NESTED_THEME_KEYS,h as SEMANTIC_COLOR_NAMES,R as VARIANT_COLOR_SOURCES,P as buildTaprootDarkTheme,J as buildTaprootLightTheme,k as encodeTheme,G as layerThemes,F as mergePartials,K as mergeTheme,_ as parseTheme,U as semanticToCSS,z as validateTheme};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/espalier",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"packageManager": "bun@1.3.12",
|
|
5
5
|
"description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
|
|
6
6
|
"customElements": "custom-elements.json",
|