@f-ewald/components 0.2.1 → 0.4.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 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) |
@@ -2488,6 +2488,30 @@
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
+ },
2507
+ {
2508
+ "kind": "js",
2509
+ "name": "MapPoint",
2510
+ "declaration": {
2511
+ "name": "MapPoint",
2512
+ "module": "./map-point.js"
2513
+ }
2514
+ },
2491
2515
  {
2492
2516
  "kind": "js",
2493
2517
  "name": "RadioCards",
@@ -2562,6 +2586,348 @@
2562
2586
  }
2563
2587
  ]
2564
2588
  },
2589
+ {
2590
+ "kind": "javascript-module",
2591
+ "path": "src/map-circle.ts",
2592
+ "declarations": [
2593
+ {
2594
+ "kind": "class",
2595
+ "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 })`.",
2596
+ "name": "MapCircle",
2597
+ "slots": [
2598
+ {
2599
+ "description": "Optional badge content shown centered on the circle — a rank number, an emoji, a small icon.",
2600
+ "name": ""
2601
+ }
2602
+ ],
2603
+ "members": [
2604
+ {
2605
+ "kind": "field",
2606
+ "name": "color",
2607
+ "type": {
2608
+ "text": "string"
2609
+ },
2610
+ "default": "\"#4f46e5\"",
2611
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2612
+ "attribute": "color"
2613
+ },
2614
+ {
2615
+ "kind": "field",
2616
+ "name": "size",
2617
+ "type": {
2618
+ "text": "number"
2619
+ },
2620
+ "default": "18",
2621
+ "description": "Diameter, in CSS pixels.",
2622
+ "attribute": "size"
2623
+ },
2624
+ {
2625
+ "kind": "field",
2626
+ "name": "ringWidth",
2627
+ "type": {
2628
+ "text": "number"
2629
+ },
2630
+ "default": "4",
2631
+ "description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
2632
+ "attribute": "ring-width"
2633
+ },
2634
+ {
2635
+ "kind": "field",
2636
+ "name": "highlighted",
2637
+ "type": {
2638
+ "text": "boolean"
2639
+ },
2640
+ "default": "false",
2641
+ "description": "Scales and glows the circle — a generic emphasis state (e.g. hover, selection).",
2642
+ "attribute": "highlighted",
2643
+ "reflects": true
2644
+ },
2645
+ {
2646
+ "kind": "field",
2647
+ "name": "_gradId",
2648
+ "privacy": "private",
2649
+ "readonly": true,
2650
+ "default": "`map-circle-grad-${gradientIdCounter++}`"
2651
+ }
2652
+ ],
2653
+ "attributes": [
2654
+ {
2655
+ "name": "color",
2656
+ "type": {
2657
+ "text": "string"
2658
+ },
2659
+ "default": "\"#4f46e5\"",
2660
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2661
+ "fieldName": "color"
2662
+ },
2663
+ {
2664
+ "name": "size",
2665
+ "type": {
2666
+ "text": "number"
2667
+ },
2668
+ "default": "18",
2669
+ "description": "Diameter, in CSS pixels.",
2670
+ "fieldName": "size"
2671
+ },
2672
+ {
2673
+ "name": "ring-width",
2674
+ "type": {
2675
+ "text": "number"
2676
+ },
2677
+ "default": "4",
2678
+ "description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
2679
+ "fieldName": "ringWidth"
2680
+ },
2681
+ {
2682
+ "name": "highlighted",
2683
+ "type": {
2684
+ "text": "boolean"
2685
+ },
2686
+ "default": "false",
2687
+ "description": "Scales and glows the circle — a generic emphasis state (e.g. hover, selection).",
2688
+ "fieldName": "highlighted"
2689
+ }
2690
+ ],
2691
+ "superclass": {
2692
+ "name": "LitElement",
2693
+ "package": "lit"
2694
+ },
2695
+ "tagName": "map-circle",
2696
+ "customElement": true
2697
+ }
2698
+ ],
2699
+ "exports": [
2700
+ {
2701
+ "kind": "js",
2702
+ "name": "MapCircle",
2703
+ "declaration": {
2704
+ "name": "MapCircle",
2705
+ "module": "src/map-circle.ts"
2706
+ }
2707
+ },
2708
+ {
2709
+ "kind": "custom-element-definition",
2710
+ "name": "map-circle",
2711
+ "declaration": {
2712
+ "name": "MapCircle",
2713
+ "module": "src/map-circle.ts"
2714
+ }
2715
+ }
2716
+ ]
2717
+ },
2718
+ {
2719
+ "kind": "javascript-module",
2720
+ "path": "src/map-pin.ts",
2721
+ "declarations": [
2722
+ {
2723
+ "kind": "class",
2724
+ "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 })`.",
2725
+ "name": "MapPin",
2726
+ "slots": [
2727
+ {
2728
+ "description": "Badge content shown centered on the pin's circular head — a rank number, an emoji, a small icon.",
2729
+ "name": ""
2730
+ }
2731
+ ],
2732
+ "members": [
2733
+ {
2734
+ "kind": "field",
2735
+ "name": "color",
2736
+ "type": {
2737
+ "text": "string"
2738
+ },
2739
+ "default": "\"#4f46e5\"",
2740
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2741
+ "attribute": "color"
2742
+ },
2743
+ {
2744
+ "kind": "field",
2745
+ "name": "size",
2746
+ "type": {
2747
+ "text": "number"
2748
+ },
2749
+ "default": "32",
2750
+ "description": "Diameter of the circular head, in CSS pixels.",
2751
+ "attribute": "size"
2752
+ },
2753
+ {
2754
+ "kind": "field",
2755
+ "name": "highlighted",
2756
+ "type": {
2757
+ "text": "boolean"
2758
+ },
2759
+ "default": "false",
2760
+ "description": "Scales and glows the pin — a generic emphasis state (e.g. hover, selection).",
2761
+ "attribute": "highlighted",
2762
+ "reflects": true
2763
+ },
2764
+ {
2765
+ "kind": "field",
2766
+ "name": "_gradId",
2767
+ "privacy": "private",
2768
+ "readonly": true,
2769
+ "default": "`map-pin-grad-${gradientIdCounter++}`"
2770
+ }
2771
+ ],
2772
+ "attributes": [
2773
+ {
2774
+ "name": "color",
2775
+ "type": {
2776
+ "text": "string"
2777
+ },
2778
+ "default": "\"#4f46e5\"",
2779
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2780
+ "fieldName": "color"
2781
+ },
2782
+ {
2783
+ "name": "size",
2784
+ "type": {
2785
+ "text": "number"
2786
+ },
2787
+ "default": "32",
2788
+ "description": "Diameter of the circular head, in CSS pixels.",
2789
+ "fieldName": "size"
2790
+ },
2791
+ {
2792
+ "name": "highlighted",
2793
+ "type": {
2794
+ "text": "boolean"
2795
+ },
2796
+ "default": "false",
2797
+ "description": "Scales and glows the pin — a generic emphasis state (e.g. hover, selection).",
2798
+ "fieldName": "highlighted"
2799
+ }
2800
+ ],
2801
+ "superclass": {
2802
+ "name": "LitElement",
2803
+ "package": "lit"
2804
+ },
2805
+ "tagName": "map-pin",
2806
+ "customElement": true
2807
+ }
2808
+ ],
2809
+ "exports": [
2810
+ {
2811
+ "kind": "js",
2812
+ "name": "MapPin",
2813
+ "declaration": {
2814
+ "name": "MapPin",
2815
+ "module": "src/map-pin.ts"
2816
+ }
2817
+ },
2818
+ {
2819
+ "kind": "custom-element-definition",
2820
+ "name": "map-pin",
2821
+ "declaration": {
2822
+ "name": "MapPin",
2823
+ "module": "src/map-pin.ts"
2824
+ }
2825
+ }
2826
+ ]
2827
+ },
2828
+ {
2829
+ "kind": "javascript-module",
2830
+ "path": "src/map-point.ts",
2831
+ "declarations": [
2832
+ {
2833
+ "kind": "class",
2834
+ "description": "A small plain-colored map marker for dense point layers (transit stops,\namenities, hazard points, etc.): a light-to-dark gradient fill with a thin\nwhite ring, no badge/content slot — every instance on a given layer shares\nthe same look, so there's nothing to render per-feature (unlike\n`<map-pin>`/`<map-circle>`, which carry per-marker slotted content).\nPurely a visual primitive — it has no `mapbox-gl` (or any mapping library)\ndependency; typically rasterized once per color and used as a Mapbox\n`icon-image` on a `symbol` layer rather than mounted as individual DOM\nmarkers, so a whole layer's worth of points shares one icon image.",
2835
+ "name": "MapPoint",
2836
+ "members": [
2837
+ {
2838
+ "kind": "field",
2839
+ "name": "color",
2840
+ "type": {
2841
+ "text": "string"
2842
+ },
2843
+ "default": "\"#4f46e5\"",
2844
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2845
+ "attribute": "color"
2846
+ },
2847
+ {
2848
+ "kind": "field",
2849
+ "name": "size",
2850
+ "type": {
2851
+ "text": "number"
2852
+ },
2853
+ "default": "14",
2854
+ "description": "Diameter, in CSS pixels.",
2855
+ "attribute": "size"
2856
+ },
2857
+ {
2858
+ "kind": "field",
2859
+ "name": "ringWidth",
2860
+ "type": {
2861
+ "text": "number"
2862
+ },
2863
+ "default": "3",
2864
+ "description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
2865
+ "attribute": "ring-width"
2866
+ },
2867
+ {
2868
+ "kind": "field",
2869
+ "name": "_gradId",
2870
+ "privacy": "private",
2871
+ "readonly": true,
2872
+ "default": "`map-point-grad-${gradientIdCounter++}`"
2873
+ }
2874
+ ],
2875
+ "attributes": [
2876
+ {
2877
+ "name": "color",
2878
+ "type": {
2879
+ "text": "string"
2880
+ },
2881
+ "default": "\"#4f46e5\"",
2882
+ "description": "Fill color; the gradient's light (top) and dark (bottom) stops are derived from this.",
2883
+ "fieldName": "color"
2884
+ },
2885
+ {
2886
+ "name": "size",
2887
+ "type": {
2888
+ "text": "number"
2889
+ },
2890
+ "default": "14",
2891
+ "description": "Diameter, in CSS pixels.",
2892
+ "fieldName": "size"
2893
+ },
2894
+ {
2895
+ "name": "ring-width",
2896
+ "type": {
2897
+ "text": "number"
2898
+ },
2899
+ "default": "3",
2900
+ "description": "White outer ring thickness, in the same viewBox units as `size` (scales with it).",
2901
+ "fieldName": "ringWidth"
2902
+ }
2903
+ ],
2904
+ "superclass": {
2905
+ "name": "LitElement",
2906
+ "package": "lit"
2907
+ },
2908
+ "tagName": "map-point",
2909
+ "customElement": true
2910
+ }
2911
+ ],
2912
+ "exports": [
2913
+ {
2914
+ "kind": "js",
2915
+ "name": "MapPoint",
2916
+ "declaration": {
2917
+ "name": "MapPoint",
2918
+ "module": "src/map-point.ts"
2919
+ }
2920
+ },
2921
+ {
2922
+ "kind": "custom-element-definition",
2923
+ "name": "map-point",
2924
+ "declaration": {
2925
+ "name": "MapPoint",
2926
+ "module": "src/map-point.ts"
2927
+ }
2928
+ }
2929
+ ]
2930
+ },
2565
2931
  {
2566
2932
  "kind": "javascript-module",
2567
2933
  "path": "src/percent-bar-chart.ts",
@@ -3784,6 +4150,52 @@
3784
4150
  }
3785
4151
  ]
3786
4152
  },
4153
+ {
4154
+ "kind": "javascript-module",
4155
+ "path": "src/utils/color.ts",
4156
+ "declarations": [
4157
+ {
4158
+ "kind": "function",
4159
+ "name": "mixHex",
4160
+ "return": {
4161
+ "type": {
4162
+ "text": "string"
4163
+ }
4164
+ },
4165
+ "parameters": [
4166
+ {
4167
+ "name": "base",
4168
+ "type": {
4169
+ "text": "string"
4170
+ }
4171
+ },
4172
+ {
4173
+ "name": "target",
4174
+ "type": {
4175
+ "text": "string"
4176
+ }
4177
+ },
4178
+ {
4179
+ "name": "weightPercent",
4180
+ "type": {
4181
+ "text": "number"
4182
+ }
4183
+ }
4184
+ ],
4185
+ "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)."
4186
+ }
4187
+ ],
4188
+ "exports": [
4189
+ {
4190
+ "kind": "js",
4191
+ "name": "mixHex",
4192
+ "declaration": {
4193
+ "name": "mixHex",
4194
+ "module": "src/utils/color.ts"
4195
+ }
4196
+ }
4197
+ ]
4198
+ },
3787
4199
  {
3788
4200
  "kind": "javascript-module",
3789
4201
  "path": "src/utils/distance.ts",
package/dist/index.d.ts CHANGED
@@ -14,6 +14,9 @@ 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";
19
+ export { MapPoint } from "./map-point.js";
17
20
  export { RadioCards, type RadioCardOption } from "./radio-cards.js";
18
21
  export { RadioPills, type RadioPillOption } from "./radio-pills.js";
19
22
  export { UiButton, type ButtonVariant } from "./ui-button.js";
@@ -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,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,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,9 @@ 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";
19
+ export { MapPoint } from "./map-point.js";
17
20
  export { RadioCards } from "./radio-cards.js";
18
21
  export { RadioPills } from "./radio-pills.js";
19
22
  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,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,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 { MapPoint } from \"./map-point.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"}
@@ -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"]}
@@ -0,0 +1,31 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * A small plain-colored map marker for dense point layers (transit stops,
4
+ * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
5
+ * white ring, no badge/content slot — every instance on a given layer shares
6
+ * the same look, so there's nothing to render per-feature (unlike
7
+ * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
8
+ * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
9
+ * dependency; typically rasterized once per color and used as a Mapbox
10
+ * `icon-image` on a `symbol` layer rather than mounted as individual DOM
11
+ * markers, so a whole layer's worth of points shares one icon image.
12
+ *
13
+ * @element map-point
14
+ */
15
+ export declare class MapPoint extends LitElement {
16
+ static styles: import("lit").CSSResult[];
17
+ /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
18
+ color: string;
19
+ /** Diameter, in CSS pixels. */
20
+ size: number;
21
+ /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
22
+ ringWidth: number;
23
+ private readonly _gradId;
24
+ render(): import("lit-html").TemplateResult<1>;
25
+ }
26
+ declare global {
27
+ interface HTMLElementTagNameMap {
28
+ "map-point": MapPoint;
29
+ }
30
+ }
31
+ //# sourceMappingURL=map-point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-point.d.ts","sourceRoot":"","sources":["../src/map-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAO5C;;;;;;;;;;;;GAYG;AACH,qBACa,QAAS,SAAQ,UAAU;IACtC,OAAgB,MAAM,4BAWpB;IAEF,4FAA4F;IAChF,KAAK,SAAa;IAC9B,+BAA+B;IACH,IAAI,SAAM;IACtC,wFAAwF;IACnC,SAAS,SAAK;IAEnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;IAE1D,MAAM,yCAoBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
@@ -0,0 +1,83 @@
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 small plain-colored map marker for dense point layers (transit stops,
14
+ * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
15
+ * white ring, no badge/content slot — every instance on a given layer shares
16
+ * the same look, so there's nothing to render per-feature (unlike
17
+ * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
18
+ * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
19
+ * dependency; typically rasterized once per color and used as a Mapbox
20
+ * `icon-image` on a `symbol` layer rather than mounted as individual DOM
21
+ * markers, so a whole layer's worth of points shares one icon image.
22
+ *
23
+ * @element map-point
24
+ */
25
+ let MapPoint = class MapPoint extends LitElement {
26
+ constructor() {
27
+ super(...arguments);
28
+ /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
29
+ this.color = "#4f46e5";
30
+ /** Diameter, in CSS pixels. */
31
+ this.size = 14;
32
+ /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
33
+ this.ringWidth = 3;
34
+ this._gradId = `map-point-grad-${gradientIdCounter++}`;
35
+ }
36
+ static { this.styles = [
37
+ tokens,
38
+ css `
39
+ :host {
40
+ display: inline-block;
41
+ line-height: 0;
42
+ }
43
+ svg {
44
+ display: block;
45
+ }
46
+ `,
47
+ ]; }
48
+ render() {
49
+ const light = mixHex(this.color, "#ffffff", 30);
50
+ const dark = mixHex(this.color, "#000000", 30);
51
+ return html `
52
+ <svg
53
+ width=${this.size}
54
+ height=${this.size}
55
+ viewBox="0 0 32 32"
56
+ fill="none"
57
+ xmlns="http://www.w3.org/2000/svg"
58
+ >
59
+ <defs>
60
+ <linearGradient id=${this._gradId} x1="0" y1="0" x2="0" y2="1">
61
+ <stop offset="0%" stop-color=${light} />
62
+ <stop offset="100%" stop-color=${dark} />
63
+ </linearGradient>
64
+ </defs>
65
+ <circle cx="16" cy="16" r="13" fill="url(#${this._gradId})" stroke="#ffffff" stroke-width=${this.ringWidth} />
66
+ </svg>
67
+ `;
68
+ }
69
+ };
70
+ __decorate([
71
+ property()
72
+ ], MapPoint.prototype, "color", void 0);
73
+ __decorate([
74
+ property({ type: Number })
75
+ ], MapPoint.prototype, "size", void 0);
76
+ __decorate([
77
+ property({ type: Number, attribute: "ring-width" })
78
+ ], MapPoint.prototype, "ringWidth", void 0);
79
+ MapPoint = __decorate([
80
+ customElement("map-point")
81
+ ], MapPoint);
82
+ export { MapPoint };
83
+ //# sourceMappingURL=map-point.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-point.js","sourceRoot":"","sources":["../src/map-point.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;;;;;;;;;;;;GAYG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;IAAjC;;QAcL,4FAA4F;QAChF,UAAK,GAAG,SAAS,CAAC;QAC9B,+BAA+B;QACH,SAAI,GAAG,EAAE,CAAC;QACtC,wFAAwF;QACnC,cAAS,GAAG,CAAC,CAAC;QAElD,YAAO,GAAG,kBAAkB,iBAAiB,EAAE,EAAE,CAAC;IAuBrE,CAAC;aA3CiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;KAQF;KACF,AAXqB,CAWpB;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,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;;KAE7G,CAAC;IACJ,CAAC;CACF,CAAA;AA7Ba;IAAX,QAAQ,EAAE;uCAAmB;AAEF;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;sCAAW;AAEe;IAApD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;2CAAe;AAnBxD,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CA4CpB","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 small plain-colored map marker for dense point layers (transit stops,\n * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin\n * white ring, no badge/content slot — every instance on a given layer shares\n * the same look, so there's nothing to render per-feature (unlike\n * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).\n * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)\n * dependency; typically rasterized once per color and used as a Mapbox\n * `icon-image` on a `symbol` layer rather than mounted as individual DOM\n * markers, so a whole layer's worth of points shares one icon image.\n *\n * @element map-point\n */\n@customElement(\"map-point\")\nexport class MapPoint extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-block;\n line-height: 0;\n }\n svg {\n display: block;\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 = 14;\n /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */\n @property({ type: Number, attribute: \"ring-width\" }) ringWidth = 3;\n\n private readonly _gradId = `map-point-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 `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"map-point\": MapPoint;\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` |
@@ -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` |
@@ -0,0 +1,43 @@
1
+ # `<map-point>`
2
+
3
+ A small plain-colored map marker for dense point layers (transit stops,
4
+ amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
5
+ white ring, no badge/content slot — every instance on a given layer shares
6
+ the same look, so there's nothing to render per-feature (unlike
7
+ `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
8
+ Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
9
+ dependency; typically rasterized once per color and used as a Mapbox
10
+ `icon-image` on a `symbol` layer rather than mounted as individual DOM
11
+ markers, so a whole layer's worth of points shares one icon image.
12
+
13
+ ## Install
14
+
15
+ ```js
16
+ import "@f-ewald/components/map-point.js";
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```html
22
+ <map-point></map-point>
23
+ ```
24
+
25
+ ## Attributes / properties
26
+
27
+ | Property | Attribute | Type | Default | Description |
28
+ | --- | --- | --- | --- | --- |
29
+ | `color` | `color` | `string` | `"#4f46e5"` | Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. |
30
+ | `size` | `size` | `number` | `14` | Diameter, in CSS pixels. |
31
+ | `ringWidth` | `ring-width` | `number` | `3` | White outer ring thickness, in the same viewBox units as `size` (scales with it). |
32
+
33
+ ## Events
34
+
35
+ _None._
36
+
37
+ ## Slots
38
+
39
+ _None._
40
+
41
+ ## CSS custom properties
42
+
43
+ _None._
package/llms.txt CHANGED
@@ -188,6 +188,68 @@ 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
+
230
+ ## <map-point>
231
+
232
+ A small plain-colored map marker for dense point layers (transit stops,
233
+ amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
234
+ white ring, no badge/content slot — every instance on a given layer shares
235
+ the same look, so there's nothing to render per-feature (unlike
236
+ `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
237
+ Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
238
+ dependency; typically rasterized once per color and used as a Mapbox
239
+ `icon-image` on a `symbol` layer rather than mounted as individual DOM
240
+ markers, so a whole layer's worth of points shares one icon image.
241
+
242
+ Import: `import "@f-ewald/components/map-point.js";`
243
+
244
+ Properties: `color` (attribute `color`) : string, default "#4f46e5"; `size` (attribute `size`) : number, default 14; `ringWidth` (attribute `ring-width`) : number, default 3
245
+ Events: none
246
+ CSS custom properties: none
247
+
248
+ Example:
249
+ ```html
250
+ <map-point></map-point>
251
+ ```
252
+
191
253
  ## <percent-bar-chart>
192
254
 
193
255
  Horizontal bar chart for labeled percentage rows, using D3's linear scale.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@f-ewald/components",
3
3
  "private": false,
4
- "version": "0.2.1",
4
+ "version": "0.4.0",
5
5
  "description": "A collection of universally usable web components for various tasks.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",