@f-ewald/components 0.2.0 → 0.3.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 +2 -0
- package/custom-elements.json +322 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/map-circle.d.ts +31 -0
- package/dist/map-circle.d.ts.map +1 -0
- package/dist/map-circle.js +108 -0
- package/dist/map-circle.js.map +1 -0
- package/dist/map-pin.d.ts +28 -0
- package/dist/map-pin.d.ts.map +1 -0
- package/dist/map-pin.js +111 -0
- package/dist/map-pin.js.map +1 -0
- package/dist/ui-button.d.ts +10 -0
- package/dist/ui-button.d.ts.map +1 -1
- package/dist/ui-button.js +17 -1
- package/dist/ui-button.js.map +1 -1
- package/dist/utils/color.d.ts +9 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/color.js +23 -0
- package/dist/utils/color.js.map +1 -0
- package/docs/map-circle.md +45 -0
- package/docs/map-pin.md +43 -0
- package/docs/ui-button.md +6 -0
- package/llms.txt +45 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,8 @@ import "@f-ewald/components/roman-numeral.js";
|
|
|
48
48
|
| `<copy-link-button>` | [docs/copy-link-button.md](./docs/copy-link-button.md) |
|
|
49
49
|
| `<distance-value>` | [docs/distance-value.md](./docs/distance-value.md) |
|
|
50
50
|
| `<distribution-chart>` | [docs/distribution-chart.md](./docs/distribution-chart.md) |
|
|
51
|
+
| `<map-circle>` | [docs/map-circle.md](./docs/map-circle.md) |
|
|
52
|
+
| `<map-pin>` | [docs/map-pin.md](./docs/map-pin.md) |
|
|
51
53
|
| `<percent-bar-chart>` | [docs/percent-bar-chart.md](./docs/percent-bar-chart.md) |
|
|
52
54
|
| `<price-history-chart>` | [docs/price-history-chart.md](./docs/price-history-chart.md) |
|
|
53
55
|
| `<radio-cards>` | [docs/radio-cards.md](./docs/radio-cards.md) |
|
package/custom-elements.json
CHANGED
|
@@ -2488,6 +2488,22 @@
|
|
|
2488
2488
|
"module": "./user-avatar.js"
|
|
2489
2489
|
}
|
|
2490
2490
|
},
|
|
2491
|
+
{
|
|
2492
|
+
"kind": "js",
|
|
2493
|
+
"name": "MapPin",
|
|
2494
|
+
"declaration": {
|
|
2495
|
+
"name": "MapPin",
|
|
2496
|
+
"module": "./map-pin.js"
|
|
2497
|
+
}
|
|
2498
|
+
},
|
|
2499
|
+
{
|
|
2500
|
+
"kind": "js",
|
|
2501
|
+
"name": "MapCircle",
|
|
2502
|
+
"declaration": {
|
|
2503
|
+
"name": "MapCircle",
|
|
2504
|
+
"module": "./map-circle.js"
|
|
2505
|
+
}
|
|
2506
|
+
},
|
|
2491
2507
|
{
|
|
2492
2508
|
"kind": "js",
|
|
2493
2509
|
"name": "RadioCards",
|
|
@@ -2562,6 +2578,245 @@
|
|
|
2562
2578
|
}
|
|
2563
2579
|
]
|
|
2564
2580
|
},
|
|
2581
|
+
{
|
|
2582
|
+
"kind": "javascript-module",
|
|
2583
|
+
"path": "src/map-circle.ts",
|
|
2584
|
+
"declarations": [
|
|
2585
|
+
{
|
|
2586
|
+
"kind": "class",
|
|
2587
|
+
"description": "A plain circular map marker: a light-to-dark gradient fill with a white\nouter ring, no point/tail (unlike `<map-pin>`) — for markers that don't\nneed to visually \"point\" at their exact coordinate. Purely a visual\nprimitive — it has no `mapbox-gl` (or any mapping library) dependency;\nthe consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.",
|
|
2588
|
+
"name": "MapCircle",
|
|
2589
|
+
"slots": [
|
|
2590
|
+
{
|
|
2591
|
+
"description": "Optional badge content shown centered on the circle — a rank number, an emoji, a small icon.",
|
|
2592
|
+
"name": ""
|
|
2593
|
+
}
|
|
2594
|
+
],
|
|
2595
|
+
"members": [
|
|
2596
|
+
{
|
|
2597
|
+
"kind": "field",
|
|
2598
|
+
"name": "color",
|
|
2599
|
+
"type": {
|
|
2600
|
+
"text": "string"
|
|
2601
|
+
},
|
|
2602
|
+
"default": "\"#4f46e5\"",
|
|
2603
|
+
"description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
|
|
2604
|
+
"attribute": "color"
|
|
2605
|
+
},
|
|
2606
|
+
{
|
|
2607
|
+
"kind": "field",
|
|
2608
|
+
"name": "size",
|
|
2609
|
+
"type": {
|
|
2610
|
+
"text": "number"
|
|
2611
|
+
},
|
|
2612
|
+
"default": "18",
|
|
2613
|
+
"description": "Diameter, in CSS pixels.",
|
|
2614
|
+
"attribute": "size"
|
|
2615
|
+
},
|
|
2616
|
+
{
|
|
2617
|
+
"kind": "field",
|
|
2618
|
+
"name": "ringWidth",
|
|
2619
|
+
"type": {
|
|
2620
|
+
"text": "number"
|
|
2621
|
+
},
|
|
2622
|
+
"default": "4",
|
|
2623
|
+
"description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
|
|
2624
|
+
"attribute": "ring-width"
|
|
2625
|
+
},
|
|
2626
|
+
{
|
|
2627
|
+
"kind": "field",
|
|
2628
|
+
"name": "highlighted",
|
|
2629
|
+
"type": {
|
|
2630
|
+
"text": "boolean"
|
|
2631
|
+
},
|
|
2632
|
+
"default": "false",
|
|
2633
|
+
"description": "Scales and glows the circle — a generic emphasis state (e.g. hover, selection).",
|
|
2634
|
+
"attribute": "highlighted",
|
|
2635
|
+
"reflects": true
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
"kind": "field",
|
|
2639
|
+
"name": "_gradId",
|
|
2640
|
+
"privacy": "private",
|
|
2641
|
+
"readonly": true,
|
|
2642
|
+
"default": "`map-circle-grad-${gradientIdCounter++}`"
|
|
2643
|
+
}
|
|
2644
|
+
],
|
|
2645
|
+
"attributes": [
|
|
2646
|
+
{
|
|
2647
|
+
"name": "color",
|
|
2648
|
+
"type": {
|
|
2649
|
+
"text": "string"
|
|
2650
|
+
},
|
|
2651
|
+
"default": "\"#4f46e5\"",
|
|
2652
|
+
"description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
|
|
2653
|
+
"fieldName": "color"
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
"name": "size",
|
|
2657
|
+
"type": {
|
|
2658
|
+
"text": "number"
|
|
2659
|
+
},
|
|
2660
|
+
"default": "18",
|
|
2661
|
+
"description": "Diameter, in CSS pixels.",
|
|
2662
|
+
"fieldName": "size"
|
|
2663
|
+
},
|
|
2664
|
+
{
|
|
2665
|
+
"name": "ring-width",
|
|
2666
|
+
"type": {
|
|
2667
|
+
"text": "number"
|
|
2668
|
+
},
|
|
2669
|
+
"default": "4",
|
|
2670
|
+
"description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
|
|
2671
|
+
"fieldName": "ringWidth"
|
|
2672
|
+
},
|
|
2673
|
+
{
|
|
2674
|
+
"name": "highlighted",
|
|
2675
|
+
"type": {
|
|
2676
|
+
"text": "boolean"
|
|
2677
|
+
},
|
|
2678
|
+
"default": "false",
|
|
2679
|
+
"description": "Scales and glows the circle — a generic emphasis state (e.g. hover, selection).",
|
|
2680
|
+
"fieldName": "highlighted"
|
|
2681
|
+
}
|
|
2682
|
+
],
|
|
2683
|
+
"superclass": {
|
|
2684
|
+
"name": "LitElement",
|
|
2685
|
+
"package": "lit"
|
|
2686
|
+
},
|
|
2687
|
+
"tagName": "map-circle",
|
|
2688
|
+
"customElement": true
|
|
2689
|
+
}
|
|
2690
|
+
],
|
|
2691
|
+
"exports": [
|
|
2692
|
+
{
|
|
2693
|
+
"kind": "js",
|
|
2694
|
+
"name": "MapCircle",
|
|
2695
|
+
"declaration": {
|
|
2696
|
+
"name": "MapCircle",
|
|
2697
|
+
"module": "src/map-circle.ts"
|
|
2698
|
+
}
|
|
2699
|
+
},
|
|
2700
|
+
{
|
|
2701
|
+
"kind": "custom-element-definition",
|
|
2702
|
+
"name": "map-circle",
|
|
2703
|
+
"declaration": {
|
|
2704
|
+
"name": "MapCircle",
|
|
2705
|
+
"module": "src/map-circle.ts"
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
]
|
|
2709
|
+
},
|
|
2710
|
+
{
|
|
2711
|
+
"kind": "javascript-module",
|
|
2712
|
+
"path": "src/map-pin.ts",
|
|
2713
|
+
"declarations": [
|
|
2714
|
+
{
|
|
2715
|
+
"kind": "class",
|
|
2716
|
+
"description": "A circular \"Apple Maps\"-style map pin: a light-to-dark gradient fill with\na slight point at the bottom. Purely a visual primitive — it has no\n`mapbox-gl` (or any mapping library) dependency; the consumer positions\nit, e.g. via `new mapboxgl.Marker({ element: pinEl })`.",
|
|
2717
|
+
"name": "MapPin",
|
|
2718
|
+
"slots": [
|
|
2719
|
+
{
|
|
2720
|
+
"description": "Badge content shown centered on the pin's circular head — a rank number, an emoji, a small icon.",
|
|
2721
|
+
"name": ""
|
|
2722
|
+
}
|
|
2723
|
+
],
|
|
2724
|
+
"members": [
|
|
2725
|
+
{
|
|
2726
|
+
"kind": "field",
|
|
2727
|
+
"name": "color",
|
|
2728
|
+
"type": {
|
|
2729
|
+
"text": "string"
|
|
2730
|
+
},
|
|
2731
|
+
"default": "\"#4f46e5\"",
|
|
2732
|
+
"description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
|
|
2733
|
+
"attribute": "color"
|
|
2734
|
+
},
|
|
2735
|
+
{
|
|
2736
|
+
"kind": "field",
|
|
2737
|
+
"name": "size",
|
|
2738
|
+
"type": {
|
|
2739
|
+
"text": "number"
|
|
2740
|
+
},
|
|
2741
|
+
"default": "32",
|
|
2742
|
+
"description": "Diameter of the circular head, in CSS pixels.",
|
|
2743
|
+
"attribute": "size"
|
|
2744
|
+
},
|
|
2745
|
+
{
|
|
2746
|
+
"kind": "field",
|
|
2747
|
+
"name": "highlighted",
|
|
2748
|
+
"type": {
|
|
2749
|
+
"text": "boolean"
|
|
2750
|
+
},
|
|
2751
|
+
"default": "false",
|
|
2752
|
+
"description": "Scales and glows the pin — a generic emphasis state (e.g. hover, selection).",
|
|
2753
|
+
"attribute": "highlighted",
|
|
2754
|
+
"reflects": true
|
|
2755
|
+
},
|
|
2756
|
+
{
|
|
2757
|
+
"kind": "field",
|
|
2758
|
+
"name": "_gradId",
|
|
2759
|
+
"privacy": "private",
|
|
2760
|
+
"readonly": true,
|
|
2761
|
+
"default": "`map-pin-grad-${gradientIdCounter++}`"
|
|
2762
|
+
}
|
|
2763
|
+
],
|
|
2764
|
+
"attributes": [
|
|
2765
|
+
{
|
|
2766
|
+
"name": "color",
|
|
2767
|
+
"type": {
|
|
2768
|
+
"text": "string"
|
|
2769
|
+
},
|
|
2770
|
+
"default": "\"#4f46e5\"",
|
|
2771
|
+
"description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
|
|
2772
|
+
"fieldName": "color"
|
|
2773
|
+
},
|
|
2774
|
+
{
|
|
2775
|
+
"name": "size",
|
|
2776
|
+
"type": {
|
|
2777
|
+
"text": "number"
|
|
2778
|
+
},
|
|
2779
|
+
"default": "32",
|
|
2780
|
+
"description": "Diameter of the circular head, in CSS pixels.",
|
|
2781
|
+
"fieldName": "size"
|
|
2782
|
+
},
|
|
2783
|
+
{
|
|
2784
|
+
"name": "highlighted",
|
|
2785
|
+
"type": {
|
|
2786
|
+
"text": "boolean"
|
|
2787
|
+
},
|
|
2788
|
+
"default": "false",
|
|
2789
|
+
"description": "Scales and glows the pin — a generic emphasis state (e.g. hover, selection).",
|
|
2790
|
+
"fieldName": "highlighted"
|
|
2791
|
+
}
|
|
2792
|
+
],
|
|
2793
|
+
"superclass": {
|
|
2794
|
+
"name": "LitElement",
|
|
2795
|
+
"package": "lit"
|
|
2796
|
+
},
|
|
2797
|
+
"tagName": "map-pin",
|
|
2798
|
+
"customElement": true
|
|
2799
|
+
}
|
|
2800
|
+
],
|
|
2801
|
+
"exports": [
|
|
2802
|
+
{
|
|
2803
|
+
"kind": "js",
|
|
2804
|
+
"name": "MapPin",
|
|
2805
|
+
"declaration": {
|
|
2806
|
+
"name": "MapPin",
|
|
2807
|
+
"module": "src/map-pin.ts"
|
|
2808
|
+
}
|
|
2809
|
+
},
|
|
2810
|
+
{
|
|
2811
|
+
"kind": "custom-element-definition",
|
|
2812
|
+
"name": "map-pin",
|
|
2813
|
+
"declaration": {
|
|
2814
|
+
"name": "MapPin",
|
|
2815
|
+
"module": "src/map-pin.ts"
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
]
|
|
2819
|
+
},
|
|
2565
2820
|
{
|
|
2566
2821
|
"kind": "javascript-module",
|
|
2567
2822
|
"path": "src/percent-bar-chart.ts",
|
|
@@ -3475,7 +3730,7 @@
|
|
|
3475
3730
|
"declarations": [
|
|
3476
3731
|
{
|
|
3477
3732
|
"kind": "class",
|
|
3478
|
-
"description": "Button (or link styled as one) with an optional leading icon, in three\nvisual weights. Set `href` to render an `<a>` instead of a `<button>` —\nsame styling either way — for cross-page navigation that should look like\nan action button; a disabled/busy link stays a real `<a>` with\n`aria-disabled` + `pointer-events: none` rather than losing its href.\nPut the icon in the `icon` slot and the label in the default slot.",
|
|
3733
|
+
"description": "Button (or link styled as one) with an optional leading icon, in three\nvisual weights. Set `href` to render an `<a>` instead of a `<button>` —\nsame styling either way — for cross-page navigation that should look like\nan action button; a disabled/busy link stays a real `<a>` with\n`aria-disabled` + `pointer-events: none` rather than losing its href.\nPut the icon in the `icon` slot and the label in the default slot.\n\nForm-associated (`type=\"submit\"`/`\"reset\"`): the actual `<button>` lives in\nthis element's shadow root, which native HTML form association does not\ncross into from an ancestor light-DOM `<form>`. `type=\"submit\"`/`\"reset\"`\nis instead wired through `ElementInternals.form` — the same mechanism\n`address-autocomplete` uses to associate with an ancestor form.",
|
|
3479
3734
|
"name": "UiButton",
|
|
3480
3735
|
"slots": [
|
|
3481
3736
|
{
|
|
@@ -3488,6 +3743,20 @@
|
|
|
3488
3743
|
}
|
|
3489
3744
|
],
|
|
3490
3745
|
"members": [
|
|
3746
|
+
{
|
|
3747
|
+
"kind": "field",
|
|
3748
|
+
"name": "formAssociated",
|
|
3749
|
+
"type": {
|
|
3750
|
+
"text": "boolean"
|
|
3751
|
+
},
|
|
3752
|
+
"static": true,
|
|
3753
|
+
"default": "true"
|
|
3754
|
+
},
|
|
3755
|
+
{
|
|
3756
|
+
"kind": "field",
|
|
3757
|
+
"name": "#internals",
|
|
3758
|
+
"privacy": "private"
|
|
3759
|
+
},
|
|
3491
3760
|
{
|
|
3492
3761
|
"kind": "field",
|
|
3493
3762
|
"name": "variant",
|
|
@@ -3537,6 +3806,12 @@
|
|
|
3537
3806
|
"default": "false",
|
|
3538
3807
|
"description": "Shows a spinner in place of the icon slot and disables the control.",
|
|
3539
3808
|
"attribute": "busy"
|
|
3809
|
+
},
|
|
3810
|
+
{
|
|
3811
|
+
"kind": "method",
|
|
3812
|
+
"name": "_onClick",
|
|
3813
|
+
"privacy": "private",
|
|
3814
|
+
"description": "Drives submit/reset on the ancestor form via ElementInternals, since a shadow-DOM button can't do it natively."
|
|
3540
3815
|
}
|
|
3541
3816
|
],
|
|
3542
3817
|
"attributes": [
|
|
@@ -3764,6 +4039,52 @@
|
|
|
3764
4039
|
}
|
|
3765
4040
|
]
|
|
3766
4041
|
},
|
|
4042
|
+
{
|
|
4043
|
+
"kind": "javascript-module",
|
|
4044
|
+
"path": "src/utils/color.ts",
|
|
4045
|
+
"declarations": [
|
|
4046
|
+
{
|
|
4047
|
+
"kind": "function",
|
|
4048
|
+
"name": "mixHex",
|
|
4049
|
+
"return": {
|
|
4050
|
+
"type": {
|
|
4051
|
+
"text": "string"
|
|
4052
|
+
}
|
|
4053
|
+
},
|
|
4054
|
+
"parameters": [
|
|
4055
|
+
{
|
|
4056
|
+
"name": "base",
|
|
4057
|
+
"type": {
|
|
4058
|
+
"text": "string"
|
|
4059
|
+
}
|
|
4060
|
+
},
|
|
4061
|
+
{
|
|
4062
|
+
"name": "target",
|
|
4063
|
+
"type": {
|
|
4064
|
+
"text": "string"
|
|
4065
|
+
}
|
|
4066
|
+
},
|
|
4067
|
+
{
|
|
4068
|
+
"name": "weightPercent",
|
|
4069
|
+
"type": {
|
|
4070
|
+
"text": "number"
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
4073
|
+
],
|
|
4074
|
+
"description": "Linearly interpolates `base` toward `target` by `weightPercent`% (0-100)\nin RGB space, returning a 6-digit hex string. Used to derive gradient\nlight/dark stops from a single base color — SVG presentation attributes\n(`stop-color`) can't consume `color-mix()`/CSS custom properties, so this\ncomputes plain hex instead (see CLAUDE.md's SVG token rule)."
|
|
4075
|
+
}
|
|
4076
|
+
],
|
|
4077
|
+
"exports": [
|
|
4078
|
+
{
|
|
4079
|
+
"kind": "js",
|
|
4080
|
+
"name": "mixHex",
|
|
4081
|
+
"declaration": {
|
|
4082
|
+
"name": "mixHex",
|
|
4083
|
+
"module": "src/utils/color.ts"
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
]
|
|
4087
|
+
},
|
|
3767
4088
|
{
|
|
3768
4089
|
"kind": "javascript-module",
|
|
3769
4090
|
"path": "src/utils/distance.ts",
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export { WeightBarChart, type WeightBarItem } from "./weight-bar-chart.js";
|
|
|
14
14
|
export { AddressAutocomplete, type AddressSuggestion, } from "./address-autocomplete.js";
|
|
15
15
|
export { AutocompleteInput, type AutocompleteOption, } from "./autocomplete-input.js";
|
|
16
16
|
export { UserAvatar } from "./user-avatar.js";
|
|
17
|
+
export { MapPin } from "./map-pin.js";
|
|
18
|
+
export { MapCircle } from "./map-circle.js";
|
|
17
19
|
export { RadioCards, type RadioCardOption } from "./radio-cards.js";
|
|
18
20
|
export { RadioPills, type RadioPillOption } from "./radio-pills.js";
|
|
19
21
|
export { UiButton, type ButtonVariant } from "./ui-button.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,EACV,KAAK,YAAY,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,EACV,KAAK,YAAY,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export { WeightBarChart } from "./weight-bar-chart.js";
|
|
|
14
14
|
export { AddressAutocomplete, } from "./address-autocomplete.js";
|
|
15
15
|
export { AutocompleteInput, } from "./autocomplete-input.js";
|
|
16
16
|
export { UserAvatar } from "./user-avatar.js";
|
|
17
|
+
export { MapPin } from "./map-pin.js";
|
|
18
|
+
export { MapCircle } from "./map-circle.js";
|
|
17
19
|
export { RadioCards } from "./radio-cards.js";
|
|
18
20
|
export { RadioPills } from "./radio-pills.js";
|
|
19
21
|
export { UiButton } from "./ui-button.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,GAEX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAA0B,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAwB,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAsB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EACL,mBAAmB,GAEpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,GAElB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAsB,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,YAAY,CAAC","sourcesContent":["export { AnimateConfetti } from \"./animate-confetti.js\";\nexport { RevealButton } from \"./reveal-button.js\";\nexport { RomanNumeral } from \"./roman-numeral.js\";\nexport { ConfirmDialog } from \"./confirm-dialog.js\";\nexport {\n ToastNotification,\n notifySuccess,\n notifyError,\n notifyInfo,\n type ToastVariant,\n} from \"./toast-notification.js\";\nexport { SlidePanel } from \"./slide-panel.js\";\nexport { CopyLinkButton } from \"./copy-link-button.js\";\nexport { RelativeTime } from \"./relative-time.js\";\nexport { DistanceValue } from \"./distance-value.js\";\nexport { PriceHistoryChart, type PricePoint } from \"./price-history-chart.js\";\nexport { DistributionChart, type DistributionValue } from \"./distribution-chart.js\";\nexport { PercentBarChart, type PercentBarGroup } from \"./percent-bar-chart.js\";\nexport { WeightBarChart, type WeightBarItem } from \"./weight-bar-chart.js\";\nexport {\n AddressAutocomplete,\n type AddressSuggestion,\n} from \"./address-autocomplete.js\";\nexport {\n AutocompleteInput,\n type AutocompleteOption,\n} from \"./autocomplete-input.js\";\nexport { UserAvatar } from \"./user-avatar.js\";\nexport { RadioCards, type RadioCardOption } from \"./radio-cards.js\";\nexport { RadioPills, type RadioPillOption } from \"./radio-pills.js\";\nexport { UiButton, type ButtonVariant } from \"./ui-button.js\";\nexport { tokens, tokenValues } from \"./tokens.js\";\nexport * from \"./icons.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,GAEX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAA0B,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAwB,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAsB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EACL,mBAAmB,GAEpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,GAElB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAsB,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,YAAY,CAAC","sourcesContent":["export { AnimateConfetti } from \"./animate-confetti.js\";\nexport { RevealButton } from \"./reveal-button.js\";\nexport { RomanNumeral } from \"./roman-numeral.js\";\nexport { ConfirmDialog } from \"./confirm-dialog.js\";\nexport {\n ToastNotification,\n notifySuccess,\n notifyError,\n notifyInfo,\n type ToastVariant,\n} from \"./toast-notification.js\";\nexport { SlidePanel } from \"./slide-panel.js\";\nexport { CopyLinkButton } from \"./copy-link-button.js\";\nexport { RelativeTime } from \"./relative-time.js\";\nexport { DistanceValue } from \"./distance-value.js\";\nexport { PriceHistoryChart, type PricePoint } from \"./price-history-chart.js\";\nexport { DistributionChart, type DistributionValue } from \"./distribution-chart.js\";\nexport { PercentBarChart, type PercentBarGroup } from \"./percent-bar-chart.js\";\nexport { WeightBarChart, type WeightBarItem } from \"./weight-bar-chart.js\";\nexport {\n AddressAutocomplete,\n type AddressSuggestion,\n} from \"./address-autocomplete.js\";\nexport {\n AutocompleteInput,\n type AutocompleteOption,\n} from \"./autocomplete-input.js\";\nexport { UserAvatar } from \"./user-avatar.js\";\nexport { MapPin } from \"./map-pin.js\";\nexport { MapCircle } from \"./map-circle.js\";\nexport { RadioCards, type RadioCardOption } from \"./radio-cards.js\";\nexport { RadioPills, type RadioPillOption } from \"./radio-pills.js\";\nexport { UiButton, type ButtonVariant } from \"./ui-button.js\";\nexport { tokens, tokenValues } from \"./tokens.js\";\nexport * from \"./icons.js\";\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
/**
|
|
3
|
+
* A plain circular map marker: a light-to-dark gradient fill with a white
|
|
4
|
+
* outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
|
|
5
|
+
* need to visually "point" at their exact coordinate. Purely a visual
|
|
6
|
+
* primitive — it has no `mapbox-gl` (or any mapping library) dependency;
|
|
7
|
+
* the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
|
|
8
|
+
*
|
|
9
|
+
* @element map-circle
|
|
10
|
+
* @slot - Optional badge content shown centered on the circle — a rank
|
|
11
|
+
* number, an emoji, a small icon.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MapCircle extends LitElement {
|
|
14
|
+
static styles: import("lit").CSSResult[];
|
|
15
|
+
/** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
|
|
16
|
+
color: string;
|
|
17
|
+
/** Diameter, in CSS pixels. */
|
|
18
|
+
size: number;
|
|
19
|
+
/** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
|
|
20
|
+
ringWidth: number;
|
|
21
|
+
/** Scales and glows the circle — a generic emphasis state (e.g. hover, selection). */
|
|
22
|
+
highlighted: boolean;
|
|
23
|
+
private readonly _gradId;
|
|
24
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
25
|
+
}
|
|
26
|
+
declare global {
|
|
27
|
+
interface HTMLElementTagNameMap {
|
|
28
|
+
"map-circle": MapCircle;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=map-circle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-circle.d.ts","sourceRoot":"","sources":["../src/map-circle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAO5C;;;;;;;;;;GAUG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC,OAAgB,MAAM,4BA8BpB;IAEF,4FAA4F;IAChF,KAAK,SAAa;IAC9B,+BAA+B;IACH,IAAI,SAAM;IACtC,wFAAwF;IACnC,SAAS,SAAK;IACnE,sFAAsF;IAC1C,WAAW,UAAS;IAEhE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IAE3D,MAAM,yCAuBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { LitElement, css, html } from "lit";
|
|
8
|
+
import { customElement, property } from "lit/decorators.js";
|
|
9
|
+
import { tokens } from "./tokens.js";
|
|
10
|
+
import { mixHex } from "./utils/color.js";
|
|
11
|
+
let gradientIdCounter = 0;
|
|
12
|
+
/**
|
|
13
|
+
* A plain circular map marker: a light-to-dark gradient fill with a white
|
|
14
|
+
* outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
|
|
15
|
+
* need to visually "point" at their exact coordinate. Purely a visual
|
|
16
|
+
* primitive — it has no `mapbox-gl` (or any mapping library) dependency;
|
|
17
|
+
* the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
|
|
18
|
+
*
|
|
19
|
+
* @element map-circle
|
|
20
|
+
* @slot - Optional badge content shown centered on the circle — a rank
|
|
21
|
+
* number, an emoji, a small icon.
|
|
22
|
+
*/
|
|
23
|
+
let MapCircle = class MapCircle extends LitElement {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
/** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
|
|
27
|
+
this.color = "#4f46e5";
|
|
28
|
+
/** Diameter, in CSS pixels. */
|
|
29
|
+
this.size = 18;
|
|
30
|
+
/** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
|
|
31
|
+
this.ringWidth = 4;
|
|
32
|
+
/** Scales and glows the circle — a generic emphasis state (e.g. hover, selection). */
|
|
33
|
+
this.highlighted = false;
|
|
34
|
+
this._gradId = `map-circle-grad-${gradientIdCounter++}`;
|
|
35
|
+
}
|
|
36
|
+
static { this.styles = [
|
|
37
|
+
tokens,
|
|
38
|
+
css `
|
|
39
|
+
:host {
|
|
40
|
+
display: inline-block;
|
|
41
|
+
position: relative;
|
|
42
|
+
line-height: 0;
|
|
43
|
+
}
|
|
44
|
+
svg {
|
|
45
|
+
display: block;
|
|
46
|
+
transition: transform 120ms ease, filter 120ms ease;
|
|
47
|
+
}
|
|
48
|
+
:host([highlighted]) svg {
|
|
49
|
+
transform: scale(1.12);
|
|
50
|
+
filter: brightness(1.08) drop-shadow(0 0 5px rgb(0 0 0 / 0.35));
|
|
51
|
+
}
|
|
52
|
+
.content {
|
|
53
|
+
position: absolute;
|
|
54
|
+
top: 50%;
|
|
55
|
+
left: 50%;
|
|
56
|
+
transform: translate(-50%, -50%);
|
|
57
|
+
color: #fff;
|
|
58
|
+
font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);
|
|
59
|
+
font-weight: 700;
|
|
60
|
+
line-height: 1;
|
|
61
|
+
text-shadow: 0 1px 2px rgb(0 0 0 / 0.35);
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
white-space: nowrap;
|
|
64
|
+
}
|
|
65
|
+
`,
|
|
66
|
+
]; }
|
|
67
|
+
render() {
|
|
68
|
+
const light = mixHex(this.color, "#ffffff", 30);
|
|
69
|
+
const dark = mixHex(this.color, "#000000", 30);
|
|
70
|
+
return html `
|
|
71
|
+
<svg
|
|
72
|
+
width=${this.size}
|
|
73
|
+
height=${this.size}
|
|
74
|
+
viewBox="0 0 32 32"
|
|
75
|
+
fill="none"
|
|
76
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
77
|
+
>
|
|
78
|
+
<defs>
|
|
79
|
+
<linearGradient id=${this._gradId} x1="0" y1="0" x2="0" y2="1">
|
|
80
|
+
<stop offset="0%" stop-color=${light} />
|
|
81
|
+
<stop offset="100%" stop-color=${dark} />
|
|
82
|
+
</linearGradient>
|
|
83
|
+
</defs>
|
|
84
|
+
<circle cx="16" cy="16" r="13" fill="url(#${this._gradId})" stroke="#ffffff" stroke-width=${this.ringWidth} />
|
|
85
|
+
</svg>
|
|
86
|
+
<div class="content" style="font-size:${Math.round(this.size * 0.4)}px">
|
|
87
|
+
<slot></slot>
|
|
88
|
+
</div>
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
__decorate([
|
|
93
|
+
property()
|
|
94
|
+
], MapCircle.prototype, "color", void 0);
|
|
95
|
+
__decorate([
|
|
96
|
+
property({ type: Number })
|
|
97
|
+
], MapCircle.prototype, "size", void 0);
|
|
98
|
+
__decorate([
|
|
99
|
+
property({ type: Number, attribute: "ring-width" })
|
|
100
|
+
], MapCircle.prototype, "ringWidth", void 0);
|
|
101
|
+
__decorate([
|
|
102
|
+
property({ type: Boolean, reflect: true })
|
|
103
|
+
], MapCircle.prototype, "highlighted", void 0);
|
|
104
|
+
MapCircle = __decorate([
|
|
105
|
+
customElement("map-circle")
|
|
106
|
+
], MapCircle);
|
|
107
|
+
export { MapCircle };
|
|
108
|
+
//# sourceMappingURL=map-circle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-circle.js","sourceRoot":"","sources":["../src/map-circle.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B;;;;;;;;;;GAUG;AAEI,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAAlC;;QAiCL,4FAA4F;QAChF,UAAK,GAAG,SAAS,CAAC;QAC9B,+BAA+B;QACH,SAAI,GAAG,EAAE,CAAC;QACtC,wFAAwF;QACnC,cAAS,GAAG,CAAC,CAAC;QACnE,sFAAsF;QAC1C,gBAAW,GAAG,KAAK,CAAC;QAE/C,YAAO,GAAG,mBAAmB,iBAAiB,EAAE,EAAE,CAAC;IA0BtE,CAAC;aAnEiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BF;KACF,AA9BqB,CA8BpB;IAaO,MAAM;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAA;;gBAEC,IAAI,CAAC,IAAI;iBACR,IAAI,CAAC,IAAI;;;;;;+BAMK,IAAI,CAAC,OAAO;2CACA,KAAK;6CACH,IAAI;;;oDAGG,IAAI,CAAC,OAAO,oCAAoC,IAAI,CAAC,SAAS;;8CAEpE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;;;KAGpE,CAAC;IACJ,CAAC;CACF,CAAA;AAlCa;IAAX,QAAQ,EAAE;wCAAmB;AAEF;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCAAW;AAEe;IAApD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;4CAAe;AAEvB;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8CAAqB;AAxCrD,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CAoErB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { mixHex } from \"./utils/color.js\";\n\nlet gradientIdCounter = 0;\n\n/**\n * A plain circular map marker: a light-to-dark gradient fill with a white\n * outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't\n * need to visually \"point\" at their exact coordinate. Purely a visual\n * primitive — it has no `mapbox-gl` (or any mapping library) dependency;\n * the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.\n *\n * @element map-circle\n * @slot - Optional badge content shown centered on the circle — a rank\n * number, an emoji, a small icon.\n */\n@customElement(\"map-circle\")\nexport class MapCircle extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-block;\n position: relative;\n line-height: 0;\n }\n svg {\n display: block;\n transition: transform 120ms ease, filter 120ms ease;\n }\n :host([highlighted]) svg {\n transform: scale(1.12);\n filter: brightness(1.08) drop-shadow(0 0 5px rgb(0 0 0 / 0.35));\n }\n .content {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: #fff;\n font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);\n font-weight: 700;\n line-height: 1;\n text-shadow: 0 1px 2px rgb(0 0 0 / 0.35);\n pointer-events: none;\n white-space: nowrap;\n }\n `,\n ];\n\n /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */\n @property() color = \"#4f46e5\";\n /** Diameter, in CSS pixels. */\n @property({ type: Number }) size = 18;\n /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */\n @property({ type: Number, attribute: \"ring-width\" }) ringWidth = 4;\n /** Scales and glows the circle — a generic emphasis state (e.g. hover, selection). */\n @property({ type: Boolean, reflect: true }) highlighted = false;\n\n private readonly _gradId = `map-circle-grad-${gradientIdCounter++}`;\n\n override render() {\n const light = mixHex(this.color, \"#ffffff\", 30);\n const dark = mixHex(this.color, \"#000000\", 30);\n return html`\n <svg\n width=${this.size}\n height=${this.size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=${this._gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=${light} />\n <stop offset=\"100%\" stop-color=${dark} />\n </linearGradient>\n </defs>\n <circle cx=\"16\" cy=\"16\" r=\"13\" fill=\"url(#${this._gradId})\" stroke=\"#ffffff\" stroke-width=${this.ringWidth} />\n </svg>\n <div class=\"content\" style=\"font-size:${Math.round(this.size * 0.4)}px\">\n <slot></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"map-circle\": MapCircle;\n }\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
/**
|
|
3
|
+
* A circular "Apple Maps"-style map pin: a light-to-dark gradient fill with
|
|
4
|
+
* a slight point at the bottom. Purely a visual primitive — it has no
|
|
5
|
+
* `mapbox-gl` (or any mapping library) dependency; the consumer positions
|
|
6
|
+
* it, e.g. via `new mapboxgl.Marker({ element: pinEl })`.
|
|
7
|
+
*
|
|
8
|
+
* @element map-pin
|
|
9
|
+
* @slot - Badge content shown centered on the pin's circular head — a rank
|
|
10
|
+
* number, an emoji, a small icon.
|
|
11
|
+
*/
|
|
12
|
+
export declare class MapPin extends LitElement {
|
|
13
|
+
static styles: import("lit").CSSResult[];
|
|
14
|
+
/** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
|
|
15
|
+
color: string;
|
|
16
|
+
/** Diameter of the circular head, in CSS pixels. */
|
|
17
|
+
size: number;
|
|
18
|
+
/** Scales and glows the pin — a generic emphasis state (e.g. hover, selection). */
|
|
19
|
+
highlighted: boolean;
|
|
20
|
+
private readonly _gradId;
|
|
21
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
22
|
+
}
|
|
23
|
+
declare global {
|
|
24
|
+
interface HTMLElementTagNameMap {
|
|
25
|
+
"map-pin": MapPin;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=map-pin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-pin.d.ts","sourceRoot":"","sources":["../src/map-pin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAO5C;;;;;;;;;GASG;AACH,qBACa,MAAO,SAAQ,UAAU;IACpC,OAAgB,MAAM,4BAiCpB;IAEF,4FAA4F;IAChF,KAAK,SAAa;IAC9B,oDAAoD;IACxB,IAAI,SAAM;IACtC,mFAAmF;IACvC,WAAW,UAAS;IAEhE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IAExD,MAAM,yCA6Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
|
package/dist/map-pin.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { LitElement, css, html } from "lit";
|
|
8
|
+
import { customElement, property } from "lit/decorators.js";
|
|
9
|
+
import { tokens } from "./tokens.js";
|
|
10
|
+
import { mixHex } from "./utils/color.js";
|
|
11
|
+
let gradientIdCounter = 0;
|
|
12
|
+
/**
|
|
13
|
+
* A circular "Apple Maps"-style map pin: a light-to-dark gradient fill with
|
|
14
|
+
* a slight point at the bottom. Purely a visual primitive — it has no
|
|
15
|
+
* `mapbox-gl` (or any mapping library) dependency; the consumer positions
|
|
16
|
+
* it, e.g. via `new mapboxgl.Marker({ element: pinEl })`.
|
|
17
|
+
*
|
|
18
|
+
* @element map-pin
|
|
19
|
+
* @slot - Badge content shown centered on the pin's circular head — a rank
|
|
20
|
+
* number, an emoji, a small icon.
|
|
21
|
+
*/
|
|
22
|
+
let MapPin = class MapPin extends LitElement {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
/** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
|
|
26
|
+
this.color = "#4f46e5";
|
|
27
|
+
/** Diameter of the circular head, in CSS pixels. */
|
|
28
|
+
this.size = 32;
|
|
29
|
+
/** Scales and glows the pin — a generic emphasis state (e.g. hover, selection). */
|
|
30
|
+
this.highlighted = false;
|
|
31
|
+
this._gradId = `map-pin-grad-${gradientIdCounter++}`;
|
|
32
|
+
}
|
|
33
|
+
static { this.styles = [
|
|
34
|
+
tokens,
|
|
35
|
+
css `
|
|
36
|
+
:host {
|
|
37
|
+
display: inline-block;
|
|
38
|
+
position: relative;
|
|
39
|
+
line-height: 0;
|
|
40
|
+
}
|
|
41
|
+
svg {
|
|
42
|
+
display: block;
|
|
43
|
+
transition: transform 120ms ease, filter 120ms ease;
|
|
44
|
+
}
|
|
45
|
+
:host([highlighted]) svg {
|
|
46
|
+
transform: scale(1.12);
|
|
47
|
+
filter: brightness(1.08) drop-shadow(0 0 5px rgb(0 0 0 / 0.35));
|
|
48
|
+
}
|
|
49
|
+
.content {
|
|
50
|
+
position: absolute;
|
|
51
|
+
/* The path's circular head is centered at viewBox y=13 of 34 total
|
|
52
|
+
(13/34 ≈ 38%) — not the pin's full bounding box, which is pulled
|
|
53
|
+
down by the point below the circle. */
|
|
54
|
+
top: 38%;
|
|
55
|
+
left: 50%;
|
|
56
|
+
transform: translate(-50%, -50%);
|
|
57
|
+
color: #fff;
|
|
58
|
+
font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);
|
|
59
|
+
font-weight: 700;
|
|
60
|
+
line-height: 1;
|
|
61
|
+
text-shadow: 0 1px 2px rgb(0 0 0 / 0.35);
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
white-space: nowrap;
|
|
64
|
+
}
|
|
65
|
+
`,
|
|
66
|
+
]; }
|
|
67
|
+
render() {
|
|
68
|
+
const light = mixHex(this.color, "#ffffff", 30);
|
|
69
|
+
const dark = mixHex(this.color, "#000000", 30);
|
|
70
|
+
const height = Math.round(this.size * (34 / 32));
|
|
71
|
+
return html `
|
|
72
|
+
<svg
|
|
73
|
+
width=${this.size}
|
|
74
|
+
height=${height}
|
|
75
|
+
viewBox="0 0 32 34"
|
|
76
|
+
fill="none"
|
|
77
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
78
|
+
>
|
|
79
|
+
<defs>
|
|
80
|
+
<linearGradient id=${this._gradId} x1="0" y1="0" x2="0" y2="1">
|
|
81
|
+
<stop offset="0%" stop-color=${light} />
|
|
82
|
+
<stop offset="100%" stop-color=${dark} />
|
|
83
|
+
</linearGradient>
|
|
84
|
+
</defs>
|
|
85
|
+
<path
|
|
86
|
+
d="M16 30 C10 24 4 19.5 4 13 A12 12 0 1 1 28 13 C28 19.5 22 24 16 30 Z"
|
|
87
|
+
fill="url(#${this._gradId})"
|
|
88
|
+
stroke="#ffffff"
|
|
89
|
+
stroke-width="1.5"
|
|
90
|
+
/>
|
|
91
|
+
</svg>
|
|
92
|
+
<div class="content" style="font-size:${Math.round(this.size * 0.4)}px">
|
|
93
|
+
<slot></slot>
|
|
94
|
+
</div>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
__decorate([
|
|
99
|
+
property()
|
|
100
|
+
], MapPin.prototype, "color", void 0);
|
|
101
|
+
__decorate([
|
|
102
|
+
property({ type: Number })
|
|
103
|
+
], MapPin.prototype, "size", void 0);
|
|
104
|
+
__decorate([
|
|
105
|
+
property({ type: Boolean, reflect: true })
|
|
106
|
+
], MapPin.prototype, "highlighted", void 0);
|
|
107
|
+
MapPin = __decorate([
|
|
108
|
+
customElement("map-pin")
|
|
109
|
+
], MapPin);
|
|
110
|
+
export { MapPin };
|
|
111
|
+
//# sourceMappingURL=map-pin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-pin.js","sourceRoot":"","sources":["../src/map-pin.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B;;;;;;;;;GASG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAO,SAAQ,UAAU;IAA/B;;QAoCL,4FAA4F;QAChF,UAAK,GAAG,SAAS,CAAC;QAC9B,oDAAoD;QACxB,SAAI,GAAG,EAAE,CAAC;QACtC,mFAAmF;QACvC,gBAAW,GAAG,KAAK,CAAC;QAE/C,YAAO,GAAG,gBAAgB,iBAAiB,EAAE,EAAE,CAAC;IAgCnE,CAAC;aA1EiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8BF;KACF,AAjCqB,CAiCpB;IAWO,MAAM;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAA;;gBAEC,IAAI,CAAC,IAAI;iBACR,MAAM;;;;;;+BAMQ,IAAI,CAAC,OAAO;2CACA,KAAK;6CACH,IAAI;;;;;uBAK1B,IAAI,CAAC,OAAO;;;;;8CAKW,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;;;KAGpE,CAAC;IACJ,CAAC;CACF,CAAA;AAtCa;IAAX,QAAQ,EAAE;qCAAmB;AAEF;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCAAW;AAEM;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;2CAAqB;AAzCrD,MAAM;IADlB,aAAa,CAAC,SAAS,CAAC;GACZ,MAAM,CA2ElB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { mixHex } from \"./utils/color.js\";\n\nlet gradientIdCounter = 0;\n\n/**\n * A circular \"Apple Maps\"-style map pin: a light-to-dark gradient fill with\n * a slight point at the bottom. Purely a visual primitive — it has no\n * `mapbox-gl` (or any mapping library) dependency; the consumer positions\n * it, e.g. via `new mapboxgl.Marker({ element: pinEl })`.\n *\n * @element map-pin\n * @slot - Badge content shown centered on the pin's circular head — a rank\n * number, an emoji, a small icon.\n */\n@customElement(\"map-pin\")\nexport class MapPin extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-block;\n position: relative;\n line-height: 0;\n }\n svg {\n display: block;\n transition: transform 120ms ease, filter 120ms ease;\n }\n :host([highlighted]) svg {\n transform: scale(1.12);\n filter: brightness(1.08) drop-shadow(0 0 5px rgb(0 0 0 / 0.35));\n }\n .content {\n position: absolute;\n /* The path's circular head is centered at viewBox y=13 of 34 total\n (13/34 ≈ 38%) — not the pin's full bounding box, which is pulled\n down by the point below the circle. */\n top: 38%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: #fff;\n font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);\n font-weight: 700;\n line-height: 1;\n text-shadow: 0 1px 2px rgb(0 0 0 / 0.35);\n pointer-events: none;\n white-space: nowrap;\n }\n `,\n ];\n\n /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */\n @property() color = \"#4f46e5\";\n /** Diameter of the circular head, in CSS pixels. */\n @property({ type: Number }) size = 32;\n /** Scales and glows the pin — a generic emphasis state (e.g. hover, selection). */\n @property({ type: Boolean, reflect: true }) highlighted = false;\n\n private readonly _gradId = `map-pin-grad-${gradientIdCounter++}`;\n\n override render() {\n const light = mixHex(this.color, \"#ffffff\", 30);\n const dark = mixHex(this.color, \"#000000\", 30);\n const height = Math.round(this.size * (34 / 32));\n return html`\n <svg\n width=${this.size}\n height=${height}\n viewBox=\"0 0 32 34\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=${this._gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=${light} />\n <stop offset=\"100%\" stop-color=${dark} />\n </linearGradient>\n </defs>\n <path\n d=\"M16 30 C10 24 4 19.5 4 13 A12 12 0 1 1 28 13 C28 19.5 22 24 16 30 Z\"\n fill=\"url(#${this._gradId})\"\n stroke=\"#ffffff\"\n stroke-width=\"1.5\"\n />\n </svg>\n <div class=\"content\" style=\"font-size:${Math.round(this.size * 0.4)}px\">\n <slot></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"map-pin\": MapPin;\n }\n}\n"]}
|
package/dist/ui-button.d.ts
CHANGED
|
@@ -8,11 +8,19 @@ export type ButtonVariant = "primary" | "secondary" | "danger";
|
|
|
8
8
|
* `aria-disabled` + `pointer-events: none` rather than losing its href.
|
|
9
9
|
* Put the icon in the `icon` slot and the label in the default slot.
|
|
10
10
|
*
|
|
11
|
+
* Form-associated (`type="submit"`/`"reset"`): the actual `<button>` lives in
|
|
12
|
+
* this element's shadow root, which native HTML form association does not
|
|
13
|
+
* cross into from an ancestor light-DOM `<form>`. `type="submit"`/`"reset"`
|
|
14
|
+
* is instead wired through `ElementInternals.form` — the same mechanism
|
|
15
|
+
* `address-autocomplete` uses to associate with an ancestor form.
|
|
16
|
+
*
|
|
11
17
|
* @element ui-button
|
|
12
18
|
* @slot icon - Optional leading icon (e.g. an inline SVG).
|
|
13
19
|
* @slot - Button label.
|
|
14
20
|
*/
|
|
15
21
|
export declare class UiButton extends LitElement {
|
|
22
|
+
#private;
|
|
23
|
+
static formAssociated: boolean;
|
|
16
24
|
static styles: import("lit").CSSResult[];
|
|
17
25
|
/** Visual weight. */
|
|
18
26
|
variant: ButtonVariant;
|
|
@@ -24,6 +32,8 @@ export declare class UiButton extends LitElement {
|
|
|
24
32
|
disabled: boolean;
|
|
25
33
|
/** Shows a spinner in place of the icon slot and disables the control. */
|
|
26
34
|
busy: boolean;
|
|
35
|
+
/** Drives submit/reset on the ancestor form via ElementInternals, since a shadow-DOM button can't do it natively. */
|
|
36
|
+
private _onClick;
|
|
27
37
|
render(): import("lit-html").TemplateResult<1>;
|
|
28
38
|
}
|
|
29
39
|
declare global {
|
package/dist/ui-button.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-button.d.ts","sourceRoot":"","sources":["../src/ui-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"ui-button.d.ts","sourceRoot":"","sources":["../src/ui-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE/D;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,QAAS,SAAQ,UAAU;;IACtC,MAAM,CAAC,cAAc,UAAQ;IAG7B,OAAgB,MAAM,4BA6DpB;IAEF,qBAAqB;IACT,OAAO,EAAE,aAAa,CAAa;IAC/C,oEAAoE;IACxD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IACvC,wDAAwD;IAC5C,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAY;IAC3D,wCAAwC;IACX,QAAQ,UAAS;IAC9C,0EAA0E;IAC7C,IAAI,UAAS;IAE1C,qHAAqH;IACrH,OAAO,CAAC,QAAQ;IAKP,MAAM,yCAmBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
|
package/dist/ui-button.js
CHANGED
|
@@ -16,6 +16,12 @@ import { tokens } from "./tokens.js";
|
|
|
16
16
|
* `aria-disabled` + `pointer-events: none` rather than losing its href.
|
|
17
17
|
* Put the icon in the `icon` slot and the label in the default slot.
|
|
18
18
|
*
|
|
19
|
+
* Form-associated (`type="submit"`/`"reset"`): the actual `<button>` lives in
|
|
20
|
+
* this element's shadow root, which native HTML form association does not
|
|
21
|
+
* cross into from an ancestor light-DOM `<form>`. `type="submit"`/`"reset"`
|
|
22
|
+
* is instead wired through `ElementInternals.form` — the same mechanism
|
|
23
|
+
* `address-autocomplete` uses to associate with an ancestor form.
|
|
24
|
+
*
|
|
19
25
|
* @element ui-button
|
|
20
26
|
* @slot icon - Optional leading icon (e.g. an inline SVG).
|
|
21
27
|
* @slot - Button label.
|
|
@@ -23,6 +29,7 @@ import { tokens } from "./tokens.js";
|
|
|
23
29
|
let UiButton = class UiButton extends LitElement {
|
|
24
30
|
constructor() {
|
|
25
31
|
super(...arguments);
|
|
32
|
+
this.#internals = this.attachInternals();
|
|
26
33
|
/** Visual weight. */
|
|
27
34
|
this.variant = "primary";
|
|
28
35
|
/** Renders an `<a href="...">` instead of a `<button>` when set. */
|
|
@@ -34,6 +41,8 @@ let UiButton = class UiButton extends LitElement {
|
|
|
34
41
|
/** Shows a spinner in place of the icon slot and disables the control. */
|
|
35
42
|
this.busy = false;
|
|
36
43
|
}
|
|
44
|
+
static { this.formAssociated = true; }
|
|
45
|
+
#internals;
|
|
37
46
|
static { this.styles = [
|
|
38
47
|
tokens,
|
|
39
48
|
css `
|
|
@@ -96,6 +105,13 @@ let UiButton = class UiButton extends LitElement {
|
|
|
96
105
|
}
|
|
97
106
|
`,
|
|
98
107
|
]; }
|
|
108
|
+
/** Drives submit/reset on the ancestor form via ElementInternals, since a shadow-DOM button can't do it natively. */
|
|
109
|
+
_onClick() {
|
|
110
|
+
if (this.type === "submit")
|
|
111
|
+
this.#internals.form?.requestSubmit();
|
|
112
|
+
else if (this.type === "reset")
|
|
113
|
+
this.#internals.form?.reset();
|
|
114
|
+
}
|
|
99
115
|
render() {
|
|
100
116
|
const classes = `btn ${this.variant}`;
|
|
101
117
|
const isDisabled = this.disabled || this.busy;
|
|
@@ -109,7 +125,7 @@ let UiButton = class UiButton extends LitElement {
|
|
|
109
125
|
`;
|
|
110
126
|
}
|
|
111
127
|
return html `
|
|
112
|
-
<button class=${classes} type
|
|
128
|
+
<button class=${classes} type="button" ?disabled=${isDisabled} @click=${this._onClick}>
|
|
113
129
|
<span class="spin" ?hidden=${!this.busy}>${iconArrowPath(14)}</span>
|
|
114
130
|
<slot name="icon" ?hidden=${this.busy}></slot>
|
|
115
131
|
<slot></slot>
|
package/dist/ui-button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-button.js","sourceRoot":"","sources":["../src/ui-button.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC
|
|
1
|
+
{"version":3,"file":"ui-button.js","sourceRoot":"","sources":["../src/ui-button.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC;;;;;;;;;;;;;;;;;GAiBG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;IAAjC;;QAGL,eAAU,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAgEpC,qBAAqB;QACT,YAAO,GAAkB,SAAS,CAAC;QAC/C,oEAAoE;QACxD,SAAI,GAAkB,IAAI,CAAC;QACvC,wDAAwD;QAC5C,SAAI,GAAkC,QAAQ,CAAC;QAC3D,wCAAwC;QACX,aAAQ,GAAG,KAAK,CAAC;QAC9C,0EAA0E;QAC7C,SAAI,GAAG,KAAK,CAAC;IA4B5C,CAAC;aAvGQ,mBAAc,GAAG,IAAI,AAAP,CAAQ;IAE7B,UAAU,CAA0B;aACpB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0DF;KACF,AA7DqB,CA6DpB;IAaF,qHAAqH;IAC7G,QAAQ;QACd,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;aAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAChE,CAAC;IAEQ,MAAM;QACb,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC;QAC9C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,IAAI,CAAA;mBACE,OAAO,SAAS,IAAI,CAAC,IAAI,kBAAkB,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;uCACpD,CAAC,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,EAAE,CAAC;sCAChC,IAAI,CAAC,IAAI;;;OAGxC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAA;sBACO,OAAO,4BAA4B,UAAU,WAAW,IAAI,CAAC,QAAQ;qCACtD,CAAC,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,EAAE,CAAC;oCAChC,IAAI,CAAC,IAAI;;;KAGxC,CAAC;IACJ,CAAC;CACF,CAAA;AApCa;IAAX,QAAQ,EAAE;yCAAoC;AAEnC;IAAX,QAAQ,EAAE;sCAA4B;AAE3B;IAAX,QAAQ,EAAE;sCAAgD;AAE9B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;0CAAkB;AAEjB;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;sCAAc;AA5E/B,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CAwGpB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { iconArrowPath } from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"danger\";\n\n/**\n * Button (or link styled as one) with an optional leading icon, in three\n * visual weights. Set `href` to render an `<a>` instead of a `<button>` —\n * same styling either way — for cross-page navigation that should look like\n * an action button; a disabled/busy link stays a real `<a>` with\n * `aria-disabled` + `pointer-events: none` rather than losing its href.\n * Put the icon in the `icon` slot and the label in the default slot.\n *\n * Form-associated (`type=\"submit\"`/`\"reset\"`): the actual `<button>` lives in\n * this element's shadow root, which native HTML form association does not\n * cross into from an ancestor light-DOM `<form>`. `type=\"submit\"`/`\"reset\"`\n * is instead wired through `ElementInternals.form` — the same mechanism\n * `address-autocomplete` uses to associate with an ancestor form.\n *\n * @element ui-button\n * @slot icon - Optional leading icon (e.g. an inline SVG).\n * @slot - Button label.\n */\n@customElement(\"ui-button\")\nexport class UiButton extends LitElement {\n static formAssociated = true;\n\n #internals = this.attachInternals();\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-flex;\n }\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n border-radius: var(--ui-radius-sm, 0.25rem);\n padding: 0.5rem 0.9rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: 500;\n font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);\n cursor: pointer;\n border: 1px solid transparent;\n text-decoration: none;\n box-sizing: border-box;\n }\n .btn.primary {\n background: var(--ui-primary, #4f46e5);\n color: #fff;\n }\n .btn.primary:hover:not(:disabled) {\n background: var(--ui-primary-hover, #4338ca);\n }\n .btn.secondary {\n background: none;\n border-color: var(--ui-border, #e2e8f0);\n color: var(--ui-text, #0f172a);\n }\n .btn.secondary:hover:not(:disabled) {\n border-color: var(--ui-text-muted, #64748b);\n }\n .btn.danger {\n background: var(--ui-danger, #dc2626);\n color: #fff;\n }\n .btn.danger:hover:not(:disabled) {\n background: var(--ui-danger-hover, #b91c1c);\n }\n .btn:disabled,\n .btn[aria-disabled=\"true\"] {\n opacity: 0.6;\n cursor: default;\n pointer-events: none;\n }\n .spin {\n display: inline-flex;\n animation: spin 0.8s linear infinite;\n }\n .spin[hidden] {\n display: none;\n }\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n `,\n ];\n\n /** Visual weight. */\n @property() variant: ButtonVariant = \"primary\";\n /** Renders an `<a href=\"...\">` instead of a `<button>` when set. */\n @property() href: string | null = null;\n /** Native button `type`. Ignored when `href` is set. */\n @property() type: \"button\" | \"submit\" | \"reset\" = \"button\";\n /** Disables the control and dims it. */\n @property({ type: Boolean }) disabled = false;\n /** Shows a spinner in place of the icon slot and disables the control. */\n @property({ type: Boolean }) busy = false;\n\n /** Drives submit/reset on the ancestor form via ElementInternals, since a shadow-DOM button can't do it natively. */\n private _onClick() {\n if (this.type === \"submit\") this.#internals.form?.requestSubmit();\n else if (this.type === \"reset\") this.#internals.form?.reset();\n }\n\n override render() {\n const classes = `btn ${this.variant}`;\n const isDisabled = this.disabled || this.busy;\n if (this.href) {\n return html`\n <a class=${classes} href=${this.href} aria-disabled=${isDisabled ? \"true\" : \"false\"}>\n <span class=\"spin\" ?hidden=${!this.busy}>${iconArrowPath(14)}</span>\n <slot name=\"icon\" ?hidden=${this.busy}></slot>\n <slot></slot>\n </a>\n `;\n }\n return html`\n <button class=${classes} type=\"button\" ?disabled=${isDisabled} @click=${this._onClick}>\n <span class=\"spin\" ?hidden=${!this.busy}>${iconArrowPath(14)}</span>\n <slot name=\"icon\" ?hidden=${this.busy}></slot>\n <slot></slot>\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ui-button\": UiButton;\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linearly interpolates `base` toward `target` by `weightPercent`% (0-100)
|
|
3
|
+
* in RGB space, returning a 6-digit hex string. Used to derive gradient
|
|
4
|
+
* light/dark stops from a single base color — SVG presentation attributes
|
|
5
|
+
* (`stop-color`) can't consume `color-mix()`/CSS custom properties, so this
|
|
6
|
+
* computes plain hex instead (see CLAUDE.md's SVG token rule).
|
|
7
|
+
*/
|
|
8
|
+
export declare function mixHex(base: string, target: string, weightPercent: number): string;
|
|
9
|
+
//# sourceMappingURL=color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/utils/color.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAOlF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Parses a 3- or 6-digit hex color string into 0-255 RGB channels. */
|
|
2
|
+
function parseHex(hex) {
|
|
3
|
+
const h = hex.replace("#", "");
|
|
4
|
+
const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
|
|
5
|
+
const num = parseInt(full, 16);
|
|
6
|
+
return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Linearly interpolates `base` toward `target` by `weightPercent`% (0-100)
|
|
10
|
+
* in RGB space, returning a 6-digit hex string. Used to derive gradient
|
|
11
|
+
* light/dark stops from a single base color — SVG presentation attributes
|
|
12
|
+
* (`stop-color`) can't consume `color-mix()`/CSS custom properties, so this
|
|
13
|
+
* computes plain hex instead (see CLAUDE.md's SVG token rule).
|
|
14
|
+
*/
|
|
15
|
+
export function mixHex(base, target, weightPercent) {
|
|
16
|
+
const b = parseHex(base);
|
|
17
|
+
const t = parseHex(target);
|
|
18
|
+
const w = Math.min(100, Math.max(0, weightPercent)) / 100;
|
|
19
|
+
const mix = (a, c) => Math.round(a + (c - a) * w);
|
|
20
|
+
const channels = [mix(b.r, t.r), mix(b.g, t.g), mix(b.b, t.b)];
|
|
21
|
+
return `#${channels.map((v) => v.toString(16).padStart(2, "0")).join("")}`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/utils/color.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,MAAc,EAAE,aAAqB;IACxE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,GAAG,GAAG,CAAC;IAC1D,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7E,CAAC","sourcesContent":["/** Parses a 3- or 6-digit hex color string into 0-255 RGB channels. */\nfunction parseHex(hex: string): { r: number; g: number; b: number } {\n const h = hex.replace(\"#\", \"\");\n const full = h.length === 3 ? h.split(\"\").map((c) => c + c).join(\"\") : h;\n const num = parseInt(full, 16);\n return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };\n}\n\n/**\n * Linearly interpolates `base` toward `target` by `weightPercent`% (0-100)\n * in RGB space, returning a 6-digit hex string. Used to derive gradient\n * light/dark stops from a single base color — SVG presentation attributes\n * (`stop-color`) can't consume `color-mix()`/CSS custom properties, so this\n * computes plain hex instead (see CLAUDE.md's SVG token rule).\n */\nexport function mixHex(base: string, target: string, weightPercent: number): string {\n const b = parseHex(base);\n const t = parseHex(target);\n const w = Math.min(100, Math.max(0, weightPercent)) / 100;\n const mix = (a: number, c: number) => Math.round(a + (c - a) * w);\n const channels = [mix(b.r, t.r), mix(b.g, t.g), mix(b.b, t.b)];\n return `#${channels.map((v) => v.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# `<map-circle>`
|
|
2
|
+
|
|
3
|
+
A plain circular map marker: a light-to-dark gradient fill with a white
|
|
4
|
+
outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
|
|
5
|
+
need to visually "point" at their exact coordinate. Purely a visual
|
|
6
|
+
primitive — it has no `mapbox-gl` (or any mapping library) dependency;
|
|
7
|
+
the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import "@f-ewald/components/map-circle.js";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<map-circle color="#6b7280"></map-circle>
|
|
19
|
+
<map-circle color="#1a73e8" size="24" ring-width="5" highlighted>1</map-circle>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Attributes / properties
|
|
23
|
+
|
|
24
|
+
| Property | Attribute | Type | Default | Description |
|
|
25
|
+
| --- | --- | --- | --- | --- |
|
|
26
|
+
| `color` | `color` | `string` | `"#4f46e5"` | Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. |
|
|
27
|
+
| `size` | `size` | `number` | `18` | Diameter, in CSS pixels. |
|
|
28
|
+
| `ringWidth` | `ring-width` | `number` | `4` | White outer ring thickness, in the same viewBox units as `size` (scales with it). |
|
|
29
|
+
| `highlighted` | `highlighted` | `boolean` | `false` | Scales and glows the circle — a generic emphasis state (e.g. hover, selection). |
|
|
30
|
+
|
|
31
|
+
## Events
|
|
32
|
+
|
|
33
|
+
_None._
|
|
34
|
+
|
|
35
|
+
## Slots
|
|
36
|
+
|
|
37
|
+
| Slot | Description |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `(default)` | Optional badge content shown centered on the circle — a rank number, an emoji, a small icon. |
|
|
40
|
+
|
|
41
|
+
## CSS custom properties
|
|
42
|
+
|
|
43
|
+
| Custom property |
|
|
44
|
+
| --- |
|
|
45
|
+
| `--ui-font` |
|
package/docs/map-pin.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# `<map-pin>`
|
|
2
|
+
|
|
3
|
+
A circular "Apple Maps"-style map pin: a light-to-dark gradient fill with
|
|
4
|
+
a slight point at the bottom. Purely a visual primitive — it has no
|
|
5
|
+
`mapbox-gl` (or any mapping library) dependency; the consumer positions
|
|
6
|
+
it, e.g. via `new mapboxgl.Marker({ element: pinEl })`.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
import "@f-ewald/components/map-pin.js";
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<map-pin color="#1a73e8" size="30">3</map-pin>
|
|
18
|
+
<map-pin color="#22c55e" size="26" highlighted>🏠</map-pin>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Attributes / properties
|
|
22
|
+
|
|
23
|
+
| Property | Attribute | Type | Default | Description |
|
|
24
|
+
| --- | --- | --- | --- | --- |
|
|
25
|
+
| `color` | `color` | `string` | `"#4f46e5"` | Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. |
|
|
26
|
+
| `size` | `size` | `number` | `32` | Diameter of the circular head, in CSS pixels. |
|
|
27
|
+
| `highlighted` | `highlighted` | `boolean` | `false` | Scales and glows the pin — a generic emphasis state (e.g. hover, selection). |
|
|
28
|
+
|
|
29
|
+
## Events
|
|
30
|
+
|
|
31
|
+
_None._
|
|
32
|
+
|
|
33
|
+
## Slots
|
|
34
|
+
|
|
35
|
+
| Slot | Description |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `(default)` | Badge content shown centered on the pin's circular head — a rank number, an emoji, a small icon. |
|
|
38
|
+
|
|
39
|
+
## CSS custom properties
|
|
40
|
+
|
|
41
|
+
| Custom property |
|
|
42
|
+
| --- |
|
|
43
|
+
| `--ui-font` |
|
package/docs/ui-button.md
CHANGED
|
@@ -7,6 +7,12 @@ an action button; a disabled/busy link stays a real `<a>` with
|
|
|
7
7
|
`aria-disabled` + `pointer-events: none` rather than losing its href.
|
|
8
8
|
Put the icon in the `icon` slot and the label in the default slot.
|
|
9
9
|
|
|
10
|
+
Form-associated (`type="submit"`/`"reset"`): the actual `<button>` lives in
|
|
11
|
+
this element's shadow root, which native HTML form association does not
|
|
12
|
+
cross into from an ancestor light-DOM `<form>`. `type="submit"`/`"reset"`
|
|
13
|
+
is instead wired through `ElementInternals.form` — the same mechanism
|
|
14
|
+
`address-autocomplete` uses to associate with an ancestor form.
|
|
15
|
+
|
|
10
16
|
## Install
|
|
11
17
|
|
|
12
18
|
```js
|
package/llms.txt
CHANGED
|
@@ -188,6 +188,45 @@ Example:
|
|
|
188
188
|
</script>
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
+
## <map-circle>
|
|
192
|
+
|
|
193
|
+
A plain circular map marker: a light-to-dark gradient fill with a white
|
|
194
|
+
outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
|
|
195
|
+
need to visually "point" at their exact coordinate. Purely a visual
|
|
196
|
+
primitive — it has no `mapbox-gl` (or any mapping library) dependency;
|
|
197
|
+
the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
|
|
198
|
+
|
|
199
|
+
Import: `import "@f-ewald/components/map-circle.js";`
|
|
200
|
+
|
|
201
|
+
Properties: `color` (attribute `color`) : string, default "#4f46e5"; `size` (attribute `size`) : number, default 18; `ringWidth` (attribute `ring-width`) : number, default 4; `highlighted` (attribute `highlighted`) : boolean, default false
|
|
202
|
+
Events: none
|
|
203
|
+
CSS custom properties: `--ui-font`
|
|
204
|
+
|
|
205
|
+
Example:
|
|
206
|
+
```html
|
|
207
|
+
<map-circle color="#6b7280"></map-circle>
|
|
208
|
+
<map-circle color="#1a73e8" size="24" ring-width="5" highlighted>1</map-circle>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## <map-pin>
|
|
212
|
+
|
|
213
|
+
A circular "Apple Maps"-style map pin: a light-to-dark gradient fill with
|
|
214
|
+
a slight point at the bottom. Purely a visual primitive — it has no
|
|
215
|
+
`mapbox-gl` (or any mapping library) dependency; the consumer positions
|
|
216
|
+
it, e.g. via `new mapboxgl.Marker({ element: pinEl })`.
|
|
217
|
+
|
|
218
|
+
Import: `import "@f-ewald/components/map-pin.js";`
|
|
219
|
+
|
|
220
|
+
Properties: `color` (attribute `color`) : string, default "#4f46e5"; `size` (attribute `size`) : number, default 32; `highlighted` (attribute `highlighted`) : boolean, default false
|
|
221
|
+
Events: none
|
|
222
|
+
CSS custom properties: `--ui-font`
|
|
223
|
+
|
|
224
|
+
Example:
|
|
225
|
+
```html
|
|
226
|
+
<map-pin color="#1a73e8" size="30">3</map-pin>
|
|
227
|
+
<map-pin color="#22c55e" size="26" highlighted>🏠</map-pin>
|
|
228
|
+
```
|
|
229
|
+
|
|
191
230
|
## <percent-bar-chart>
|
|
192
231
|
|
|
193
232
|
Horizontal bar chart for labeled percentage rows, using D3's linear scale.
|
|
@@ -398,6 +437,12 @@ an action button; a disabled/busy link stays a real `<a>` with
|
|
|
398
437
|
`aria-disabled` + `pointer-events: none` rather than losing its href.
|
|
399
438
|
Put the icon in the `icon` slot and the label in the default slot.
|
|
400
439
|
|
|
440
|
+
Form-associated (`type="submit"`/`"reset"`): the actual `<button>` lives in
|
|
441
|
+
this element's shadow root, which native HTML form association does not
|
|
442
|
+
cross into from an ancestor light-DOM `<form>`. `type="submit"`/`"reset"`
|
|
443
|
+
is instead wired through `ElementInternals.form` — the same mechanism
|
|
444
|
+
`address-autocomplete` uses to associate with an ancestor form.
|
|
445
|
+
|
|
401
446
|
Import: `import "@f-ewald/components/ui-button.js";`
|
|
402
447
|
|
|
403
448
|
Properties: `variant` (attribute `variant`) : ButtonVariant, default "primary"; `href` (attribute `href`) : string | null, default null; `type` (attribute `type`) : "button" | "submit" | "reset", default "button"; `disabled` (attribute `disabled`) : boolean, default false; `busy` (attribute `busy`) : boolean, default false
|