@phcdevworks/spectre-components 1.6.0 → 1.7.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.
Files changed (110) hide show
  1. package/README.md +174 -1
  2. package/dist/alert.cjs.map +1 -1
  3. package/dist/alert.d.cts +2 -2
  4. package/dist/alert.d.ts +2 -2
  5. package/dist/alert.js.map +1 -1
  6. package/dist/avatar.cjs.map +1 -1
  7. package/dist/avatar.d.cts +2 -2
  8. package/dist/avatar.d.ts +2 -2
  9. package/dist/avatar.js.map +1 -1
  10. package/dist/badge.cjs.map +1 -1
  11. package/dist/badge.d.cts +2 -2
  12. package/dist/badge.d.ts +2 -2
  13. package/dist/badge.js.map +1 -1
  14. package/dist/button.cjs.map +1 -1
  15. package/dist/button.d.cts +2 -2
  16. package/dist/button.d.ts +2 -2
  17. package/dist/button.js.map +1 -1
  18. package/dist/card.cjs.map +1 -1
  19. package/dist/card.d.cts +2 -2
  20. package/dist/card.d.ts +2 -2
  21. package/dist/card.js.map +1 -1
  22. package/dist/container.cjs.map +1 -1
  23. package/dist/container.d.cts +2 -2
  24. package/dist/container.d.ts +2 -2
  25. package/dist/container.js.map +1 -1
  26. package/dist/dropdown.cjs +486 -0
  27. package/dist/dropdown.cjs.map +1 -0
  28. package/dist/dropdown.d.cts +69 -0
  29. package/dist/dropdown.d.ts +69 -0
  30. package/dist/dropdown.js +482 -0
  31. package/dist/dropdown.js.map +1 -0
  32. package/dist/{form-8KZeQRgr.d.cts → form-DgzRhNmg.d.cts} +7 -1
  33. package/dist/{form-8KZeQRgr.d.ts → form-DgzRhNmg.d.ts} +7 -1
  34. package/dist/grid.cjs.map +1 -1
  35. package/dist/grid.d.cts +2 -2
  36. package/dist/grid.d.ts +2 -2
  37. package/dist/grid.js.map +1 -1
  38. package/dist/icon-box.cjs.map +1 -1
  39. package/dist/icon-box.d.cts +2 -2
  40. package/dist/icon-box.d.ts +2 -2
  41. package/dist/icon-box.js.map +1 -1
  42. package/dist/index.cjs +924 -0
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +7 -1
  45. package/dist/index.d.ts +7 -1
  46. package/dist/index.js +911 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/input.cjs.map +1 -1
  49. package/dist/input.d.cts +2 -2
  50. package/dist/input.d.ts +2 -2
  51. package/dist/input.js.map +1 -1
  52. package/dist/modal.cjs +519 -0
  53. package/dist/modal.cjs.map +1 -0
  54. package/dist/modal.d.cts +52 -0
  55. package/dist/modal.d.ts +52 -0
  56. package/dist/modal.js +516 -0
  57. package/dist/modal.js.map +1 -0
  58. package/dist/nav.cjs +424 -0
  59. package/dist/nav.cjs.map +1 -0
  60. package/dist/nav.d.cts +45 -0
  61. package/dist/nav.d.ts +45 -0
  62. package/dist/nav.js +421 -0
  63. package/dist/nav.js.map +1 -0
  64. package/dist/rating.cjs.map +1 -1
  65. package/dist/rating.d.cts +2 -2
  66. package/dist/rating.d.ts +2 -2
  67. package/dist/rating.js.map +1 -1
  68. package/dist/select.cjs.map +1 -1
  69. package/dist/select.d.cts +1 -1
  70. package/dist/select.d.ts +1 -1
  71. package/dist/select.js.map +1 -1
  72. package/dist/sidebar.cjs +481 -0
  73. package/dist/sidebar.cjs.map +1 -0
  74. package/dist/sidebar.d.cts +50 -0
  75. package/dist/sidebar.d.ts +50 -0
  76. package/dist/sidebar.js +478 -0
  77. package/dist/sidebar.js.map +1 -0
  78. package/dist/spinner.cjs.map +1 -1
  79. package/dist/spinner.d.cts +2 -2
  80. package/dist/spinner.d.ts +2 -2
  81. package/dist/spinner.js.map +1 -1
  82. package/dist/stack.cjs.map +1 -1
  83. package/dist/stack.d.cts +2 -2
  84. package/dist/stack.d.ts +2 -2
  85. package/dist/stack.js.map +1 -1
  86. package/dist/tag.cjs.map +1 -1
  87. package/dist/tag.d.cts +2 -2
  88. package/dist/tag.d.ts +2 -2
  89. package/dist/tag.js.map +1 -1
  90. package/dist/testimonial.cjs.map +1 -1
  91. package/dist/testimonial.d.cts +2 -2
  92. package/dist/testimonial.d.ts +2 -2
  93. package/dist/testimonial.js.map +1 -1
  94. package/dist/textarea.cjs.map +1 -1
  95. package/dist/textarea.d.cts +1 -1
  96. package/dist/textarea.d.ts +1 -1
  97. package/dist/textarea.js.map +1 -1
  98. package/dist/toast.cjs +475 -0
  99. package/dist/toast.cjs.map +1 -0
  100. package/dist/toast.d.cts +68 -0
  101. package/dist/toast.d.ts +68 -0
  102. package/dist/toast.js +471 -0
  103. package/dist/toast.js.map +1 -0
  104. package/dist/tooltip.cjs +444 -0
  105. package/dist/tooltip.cjs.map +1 -0
  106. package/dist/tooltip.d.cts +50 -0
  107. package/dist/tooltip.d.ts +50 -0
  108. package/dist/tooltip.js +440 -0
  109. package/dist/tooltip.js.map +1 -0
  110. package/package.json +34 -4
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getButtonClasses, getInputLabelClasses, getInputClasses, getTextareaClasses, getSelectClasses, getCheckboxClasses, getRadioClasses, getLabelClasses, getFieldsetLegendClasses, getFieldsetClasses, getBadgeClasses, getCardClasses, getIconBoxClasses, getRatingClasses, getRatingStarClasses, getRatingStarsClasses, getRatingTextClasses, getTestimonialClasses, getAlertClasses, getAvatarClasses, getSpinnerClasses, getTagClasses, getPricingCardClasses, getContainerClasses, getGridClasses, getStackClasses, getSectionClasses } from '@phcdevworks/spectre-ui';
1
+ import { getButtonClasses, getInputLabelClasses, getInputClasses, getTextareaClasses, getSelectClasses, getCheckboxClasses, getRadioClasses, getLabelClasses, getFieldsetLegendClasses, getFieldsetClasses, getBadgeClasses, getCardClasses, getIconBoxClasses, getRatingClasses, getRatingStarClasses, getRatingStarsClasses, getRatingTextClasses, getTestimonialClasses, getAlertClasses, getAvatarClasses, getSpinnerClasses, getTagClasses, getPricingCardClasses, getContainerClasses, getGridClasses, getStackClasses, getDropdownClasses, getDropdownMenuClasses, getModalOverlayClasses, getModalClasses, getNavClasses, getSidebarClasses, getSidebarToggleClasses, getSidebarBackdropClasses, getToastClasses, getToastIconClasses, getTooltipClasses, getSectionClasses } from '@phcdevworks/spectre-ui';
2
2
  import { LitElement, html, nothing } from 'lit';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
4
  import { live } from 'lit/directives/live.js';
@@ -170,6 +170,37 @@ var spectreStackAligns = ["center", "stretch"];
170
170
  function isStackAlign(value) {
171
171
  return spectreStackAligns.includes(value);
172
172
  }
173
+ var spectreDropdownPlacements = [
174
+ "bottom-start",
175
+ "bottom-end",
176
+ "top-start",
177
+ "top-end"
178
+ ];
179
+ function isDropdownPlacement(value) {
180
+ return spectreDropdownPlacements.includes(
181
+ value
182
+ );
183
+ }
184
+ var spectreToastVariants = [
185
+ "info",
186
+ "success",
187
+ "warning",
188
+ "danger"
189
+ ];
190
+ function isToastVariant(value) {
191
+ return spectreToastVariants.includes(value);
192
+ }
193
+ var spectreTooltipPlacements = [
194
+ "top",
195
+ "bottom",
196
+ "left",
197
+ "right"
198
+ ];
199
+ function isTooltipPlacement(value) {
200
+ return spectreTooltipPlacements.includes(
201
+ value
202
+ );
203
+ }
173
204
  function normalizeInt(value, fallback, min = 0) {
174
205
  if (value == null || typeof value !== "number" || !Number.isInteger(value) || value < min) {
175
206
  return fallback;
@@ -2884,6 +2915,878 @@ function defineSpectreStack(tagName = "sp-stack") {
2884
2915
  customElements.define(tagName, SpectreStackElement);
2885
2916
  return SpectreStackElement;
2886
2917
  }
2918
+ var SpectreDropdownElement = class extends SpectreBaseElement {
2919
+ constructor() {
2920
+ super(...arguments);
2921
+ this.fullWidth = false;
2922
+ this.open = false;
2923
+ this.placement = "bottom-start";
2924
+ this.triggerLabel = "Toggle menu";
2925
+ this.triggerContent = [];
2926
+ this.menuContent = [];
2927
+ this.handleDocumentClick = (event) => {
2928
+ if (!this.open) {
2929
+ return;
2930
+ }
2931
+ if (!event.composedPath().includes(this)) {
2932
+ this.close();
2933
+ }
2934
+ };
2935
+ this.handleDocumentKeydown = (event) => {
2936
+ if (event.key === "Escape" && this.open) {
2937
+ this.close();
2938
+ this.triggerElement?.focus();
2939
+ }
2940
+ };
2941
+ }
2942
+ get id() {
2943
+ return super.id;
2944
+ }
2945
+ set id(value) {
2946
+ super.id = value;
2947
+ }
2948
+ get title() {
2949
+ return super.title;
2950
+ }
2951
+ set title(value) {
2952
+ super.title = value;
2953
+ }
2954
+ isInternalNode(node) {
2955
+ if (node.nodeType !== Node.ELEMENT_NODE) {
2956
+ return false;
2957
+ }
2958
+ const el = node;
2959
+ return el.hasAttribute("data-sp-dropdown-menu") || el.hasAttribute("data-sp-dropdown-trigger");
2960
+ }
2961
+ syncProjectedContent() {
2962
+ const nextTriggerContent = [];
2963
+ const nextMenuContent = [];
2964
+ this.childNodes.forEach((node) => {
2965
+ if (this.isInternalNode(node)) {
2966
+ return;
2967
+ }
2968
+ const isTriggerSlot = node.nodeType === Node.ELEMENT_NODE && node.getAttribute("slot") === "trigger";
2969
+ if (isTriggerSlot) {
2970
+ nextTriggerContent.push(node);
2971
+ } else {
2972
+ nextMenuContent.push(node);
2973
+ }
2974
+ });
2975
+ const changed = nextTriggerContent.length !== this.triggerContent.length || nextTriggerContent.some((n, i) => n !== this.triggerContent[i]) || nextMenuContent.length !== this.menuContent.length || nextMenuContent.some((n, i) => n !== this.menuContent[i]);
2976
+ if (changed) {
2977
+ this.triggerContent = nextTriggerContent;
2978
+ this.menuContent = nextMenuContent;
2979
+ }
2980
+ return changed;
2981
+ }
2982
+ get hasTriggerContent() {
2983
+ return hasMeaningfulContent(this.triggerContent);
2984
+ }
2985
+ get hasMenuContent() {
2986
+ return hasMeaningfulContent(this.menuContent);
2987
+ }
2988
+ connectedCallback() {
2989
+ super.connectedCallback();
2990
+ this.syncProjectedContent();
2991
+ this.startContentObserver();
2992
+ document.addEventListener("click", this.handleDocumentClick);
2993
+ document.addEventListener("keydown", this.handleDocumentKeydown);
2994
+ }
2995
+ disconnectedCallback() {
2996
+ this.stopContentObserver();
2997
+ document.removeEventListener("click", this.handleDocumentClick);
2998
+ document.removeEventListener("keydown", this.handleDocumentKeydown);
2999
+ super.disconnectedCallback();
3000
+ }
3001
+ update(changedProperties) {
3002
+ this.stopContentObserver();
3003
+ super.update(changedProperties);
3004
+ this.startContentObserver();
3005
+ }
3006
+ startContentObserver() {
3007
+ if (this.contentObserver) {
3008
+ return;
3009
+ }
3010
+ this.contentObserver = new MutationObserver(() => {
3011
+ if (this.syncProjectedContent()) {
3012
+ this.requestUpdate();
3013
+ }
3014
+ });
3015
+ this.contentObserver.observe(this, { childList: true });
3016
+ }
3017
+ stopContentObserver() {
3018
+ this.contentObserver?.disconnect();
3019
+ this.contentObserver = void 0;
3020
+ }
3021
+ willUpdate(changedProperties) {
3022
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3023
+ this.fullWidth = false;
3024
+ }
3025
+ if (changedProperties.has("open") && this.open == null) {
3026
+ this.open = false;
3027
+ }
3028
+ if (changedProperties.has("placement") && (this.placement == null || !isDropdownPlacement(this.placement))) {
3029
+ this.placement = "bottom-start";
3030
+ }
3031
+ if (changedProperties.has("triggerLabel") && !this.triggerLabel) {
3032
+ this.triggerLabel = "Toggle menu";
3033
+ }
3034
+ }
3035
+ get triggerElement() {
3036
+ return this.querySelector("[data-sp-dropdown-trigger]");
3037
+ }
3038
+ toggle() {
3039
+ if (this.open) {
3040
+ this.close();
3041
+ } else {
3042
+ this.openMenu();
3043
+ }
3044
+ }
3045
+ openMenu() {
3046
+ if (this.open) {
3047
+ return;
3048
+ }
3049
+ this.open = true;
3050
+ this.dispatchEvent(new CustomEvent("sp-open", { bubbles: true }));
3051
+ }
3052
+ close() {
3053
+ if (!this.open) {
3054
+ return;
3055
+ }
3056
+ this.open = false;
3057
+ this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
3058
+ }
3059
+ get dropdownClasses() {
3060
+ return getDropdownClasses({ fullWidth: this.fullWidth ?? false });
3061
+ }
3062
+ get menuClasses() {
3063
+ return getDropdownMenuClasses({
3064
+ open: this.open ?? false,
3065
+ placement: this.placement
3066
+ });
3067
+ }
3068
+ render() {
3069
+ return html`<div
3070
+ class="${this.dropdownClasses}"
3071
+ id="${ifDefined(this.id || void 0)}"
3072
+ title="${ifDefined(this.title || void 0)}"
3073
+ >
3074
+ <button
3075
+ aria-expanded="${this.open ? "true" : "false"}"
3076
+ aria-haspopup="true"
3077
+ aria-label="${ifDefined(this.forwardedAriaLabel ?? this.triggerLabel)}"
3078
+ class="sp-dropdown__trigger"
3079
+ data-sp-dropdown-trigger
3080
+ type="button"
3081
+ @click="${() => this.toggle()}"
3082
+ >
3083
+ ${this.hasTriggerContent ? this.triggerContent : this.triggerLabel}
3084
+ </button>
3085
+ <div class="${this.menuClasses}" data-sp-dropdown-menu>
3086
+ ${this.hasMenuContent ? this.menuContent : nothing}
3087
+ </div>
3088
+ </div>`;
3089
+ }
3090
+ };
3091
+ SpectreDropdownElement.properties = {
3092
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3093
+ open: { type: Boolean, reflect: true },
3094
+ placement: { type: String, reflect: true },
3095
+ triggerLabel: { attribute: "trigger-label", type: String }
3096
+ };
3097
+ function defineSpectreDropdown(tagName = "sp-dropdown") {
3098
+ const existingElement = customElements.get(tagName);
3099
+ if (existingElement) {
3100
+ return existingElement;
3101
+ }
3102
+ customElements.define(tagName, SpectreDropdownElement);
3103
+ return SpectreDropdownElement;
3104
+ }
3105
+ var FOCUSABLE_SELECTOR = [
3106
+ "a[href]",
3107
+ "button:not([disabled])",
3108
+ "input:not([disabled])",
3109
+ "select:not([disabled])",
3110
+ "textarea:not([disabled])",
3111
+ '[tabindex]:not([tabindex="-1"])'
3112
+ ].join(",");
3113
+ var SpectreModalElement = class extends SpectreProjectableElement {
3114
+ constructor() {
3115
+ super(...arguments);
3116
+ this.fullWidth = false;
3117
+ this.open = false;
3118
+ this.previouslyFocusedElement = null;
3119
+ this.handleDocumentKeydown = (event) => {
3120
+ if (!this.open) {
3121
+ return;
3122
+ }
3123
+ if (event.key === "Escape") {
3124
+ this.close();
3125
+ return;
3126
+ }
3127
+ if (event.key === "Tab") {
3128
+ this.trapFocus(event);
3129
+ }
3130
+ };
3131
+ }
3132
+ get id() {
3133
+ return super.id;
3134
+ }
3135
+ set id(value) {
3136
+ super.id = value;
3137
+ }
3138
+ get title() {
3139
+ return super.title;
3140
+ }
3141
+ set title(value) {
3142
+ super.title = value;
3143
+ }
3144
+ getContentContainer() {
3145
+ return this.querySelector("[data-sp-modal-native]");
3146
+ }
3147
+ isInternalNode(node) {
3148
+ if (node.nodeType !== Node.ELEMENT_NODE) {
3149
+ return false;
3150
+ }
3151
+ const el = node;
3152
+ return el.hasAttribute("data-sp-modal-native") || el.hasAttribute("data-sp-modal-overlay");
3153
+ }
3154
+ willUpdate(changedProperties) {
3155
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3156
+ this.fullWidth = false;
3157
+ }
3158
+ if (changedProperties.has("open") && this.open == null) {
3159
+ this.open = false;
3160
+ }
3161
+ }
3162
+ updated(changedProperties) {
3163
+ super.updated(changedProperties);
3164
+ if (!changedProperties.has("open")) {
3165
+ return;
3166
+ }
3167
+ if (this.open) {
3168
+ this.previouslyFocusedElement = document.activeElement;
3169
+ this.focusFirstElement();
3170
+ } else if (this.previouslyFocusedElement) {
3171
+ this.previouslyFocusedElement.focus();
3172
+ this.previouslyFocusedElement = null;
3173
+ }
3174
+ }
3175
+ connectedCallback() {
3176
+ super.connectedCallback();
3177
+ document.addEventListener("keydown", this.handleDocumentKeydown);
3178
+ }
3179
+ disconnectedCallback() {
3180
+ document.removeEventListener("keydown", this.handleDocumentKeydown);
3181
+ super.disconnectedCallback();
3182
+ }
3183
+ get modalElement() {
3184
+ return this.querySelector("[data-sp-modal-native]");
3185
+ }
3186
+ get focusableElements() {
3187
+ const modal = this.modalElement;
3188
+ if (!modal) {
3189
+ return [];
3190
+ }
3191
+ return Array.from(modal.querySelectorAll(FOCUSABLE_SELECTOR));
3192
+ }
3193
+ focusFirstElement() {
3194
+ const [first] = this.focusableElements;
3195
+ (first ?? this.modalElement)?.focus();
3196
+ }
3197
+ trapFocus(event) {
3198
+ const focusable = this.focusableElements;
3199
+ if (focusable.length === 0) {
3200
+ event.preventDefault();
3201
+ return;
3202
+ }
3203
+ const first = focusable[0];
3204
+ const last = focusable[focusable.length - 1];
3205
+ const active = document.activeElement;
3206
+ if (event.shiftKey && active === first) {
3207
+ event.preventDefault();
3208
+ last?.focus();
3209
+ } else if (!event.shiftKey && active === last) {
3210
+ event.preventDefault();
3211
+ first?.focus();
3212
+ }
3213
+ }
3214
+ close() {
3215
+ if (!this.open) {
3216
+ return;
3217
+ }
3218
+ this.open = false;
3219
+ this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
3220
+ }
3221
+ get overlayClasses() {
3222
+ return getModalOverlayClasses({ open: this.open ?? false });
3223
+ }
3224
+ get modalClasses() {
3225
+ return getModalClasses({
3226
+ open: this.open ?? false,
3227
+ fullWidth: this.fullWidth ?? false
3228
+ });
3229
+ }
3230
+ render() {
3231
+ const isHidden = !this.open;
3232
+ return html`<div
3233
+ aria-hidden="${ifDefined(isHidden ? "true" : void 0)}"
3234
+ class="${this.overlayClasses}"
3235
+ data-sp-modal-overlay
3236
+ @click="${(event) => {
3237
+ if (event.target === event.currentTarget) {
3238
+ this.close();
3239
+ }
3240
+ }}"
3241
+ >
3242
+ <div
3243
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
3244
+ aria-hidden="${ifDefined(isHidden ? "true" : void 0)}"
3245
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
3246
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
3247
+ aria-modal="true"
3248
+ class="${this.modalClasses}"
3249
+ data-sp-modal-native
3250
+ id="${ifDefined(this.id || void 0)}"
3251
+ role="dialog"
3252
+ tabindex="-1"
3253
+ title="${ifDefined(this.title || void 0)}"
3254
+ >
3255
+ ${this.hasProjectedContent ? this.projectedContent : nothing}
3256
+ </div>
3257
+ </div>`;
3258
+ }
3259
+ };
3260
+ SpectreModalElement.properties = {
3261
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3262
+ open: { type: Boolean, reflect: true }
3263
+ };
3264
+ function defineSpectreModal(tagName = "sp-modal") {
3265
+ const existingElement = customElements.get(tagName);
3266
+ if (existingElement) {
3267
+ return existingElement;
3268
+ }
3269
+ customElements.define(tagName, SpectreModalElement);
3270
+ return SpectreModalElement;
3271
+ }
3272
+ var SpectreNavElement = class extends SpectreProjectableElement {
3273
+ constructor() {
3274
+ super(...arguments);
3275
+ this.bordered = false;
3276
+ this.fullWidth = false;
3277
+ this.sticky = false;
3278
+ }
3279
+ get id() {
3280
+ return super.id;
3281
+ }
3282
+ set id(value) {
3283
+ super.id = value;
3284
+ }
3285
+ get title() {
3286
+ return super.title;
3287
+ }
3288
+ set title(value) {
3289
+ super.title = value;
3290
+ }
3291
+ getContentContainer() {
3292
+ return this.querySelector("[data-sp-nav-native]");
3293
+ }
3294
+ isInternalNode(node) {
3295
+ if (node.nodeType !== Node.ELEMENT_NODE) {
3296
+ return false;
3297
+ }
3298
+ const el = node;
3299
+ return el.hasAttribute("data-sp-nav-native");
3300
+ }
3301
+ willUpdate(changedProperties) {
3302
+ if (changedProperties.has("bordered") && this.bordered == null) {
3303
+ this.bordered = false;
3304
+ }
3305
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3306
+ this.fullWidth = false;
3307
+ }
3308
+ if (changedProperties.has("sticky") && this.sticky == null) {
3309
+ this.sticky = false;
3310
+ }
3311
+ }
3312
+ get navClasses() {
3313
+ return getNavClasses({
3314
+ bordered: this.bordered ?? false,
3315
+ fullWidth: this.fullWidth ?? false,
3316
+ sticky: this.sticky ?? false
3317
+ });
3318
+ }
3319
+ render() {
3320
+ return html`<nav
3321
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
3322
+ class="${this.navClasses}"
3323
+ data-sp-nav-native
3324
+ id="${ifDefined(this.id || void 0)}"
3325
+ title="${ifDefined(this.title || void 0)}"
3326
+ >
3327
+ ${this.hasProjectedContent ? this.projectedContent : nothing}
3328
+ </nav>`;
3329
+ }
3330
+ };
3331
+ SpectreNavElement.properties = {
3332
+ bordered: { type: Boolean, reflect: true },
3333
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3334
+ sticky: { type: Boolean, reflect: true }
3335
+ };
3336
+ function defineSpectreNav(tagName = "sp-nav") {
3337
+ const existingElement = customElements.get(tagName);
3338
+ if (existingElement) {
3339
+ return existingElement;
3340
+ }
3341
+ customElements.define(tagName, SpectreNavElement);
3342
+ return SpectreNavElement;
3343
+ }
3344
+ var SpectreSidebarElement = class extends SpectreProjectableElement {
3345
+ constructor() {
3346
+ super(...arguments);
3347
+ this.bordered = false;
3348
+ this.open = false;
3349
+ this.toggleLabel = "Toggle sidebar";
3350
+ this.handleDocumentKeydown = (event) => {
3351
+ if (event.key === "Escape" && this.open) {
3352
+ this.close();
3353
+ }
3354
+ };
3355
+ }
3356
+ get id() {
3357
+ return super.id;
3358
+ }
3359
+ set id(value) {
3360
+ super.id = value;
3361
+ }
3362
+ get title() {
3363
+ return super.title;
3364
+ }
3365
+ set title(value) {
3366
+ super.title = value;
3367
+ }
3368
+ getContentContainer() {
3369
+ return this.querySelector("[data-sp-sidebar-native]");
3370
+ }
3371
+ isInternalNode(node) {
3372
+ if (node.nodeType !== Node.ELEMENT_NODE) {
3373
+ return false;
3374
+ }
3375
+ const el = node;
3376
+ return el.hasAttribute("data-sp-sidebar-native") || el.hasAttribute("data-sp-sidebar-toggle") || el.hasAttribute("data-sp-sidebar-backdrop");
3377
+ }
3378
+ willUpdate(changedProperties) {
3379
+ if (changedProperties.has("bordered") && this.bordered == null) {
3380
+ this.bordered = false;
3381
+ }
3382
+ if (changedProperties.has("open") && this.open == null) {
3383
+ this.open = false;
3384
+ }
3385
+ if (changedProperties.has("toggleLabel") && !this.toggleLabel) {
3386
+ this.toggleLabel = "Toggle sidebar";
3387
+ }
3388
+ if (changedProperties.has("open")) {
3389
+ HTMLElement.prototype.setAttribute.call(
3390
+ this,
3391
+ "data-sidebar-open",
3392
+ this.open ? "true" : "false"
3393
+ );
3394
+ }
3395
+ }
3396
+ connectedCallback() {
3397
+ super.connectedCallback();
3398
+ HTMLElement.prototype.setAttribute.call(
3399
+ this,
3400
+ "data-sidebar-open",
3401
+ this.open ? "true" : "false"
3402
+ );
3403
+ document.addEventListener("keydown", this.handleDocumentKeydown);
3404
+ }
3405
+ disconnectedCallback() {
3406
+ document.removeEventListener("keydown", this.handleDocumentKeydown);
3407
+ super.disconnectedCallback();
3408
+ }
3409
+ toggle() {
3410
+ if (this.open) {
3411
+ this.close();
3412
+ } else {
3413
+ this.openSidebar();
3414
+ }
3415
+ }
3416
+ openSidebar() {
3417
+ if (this.open) {
3418
+ return;
3419
+ }
3420
+ this.open = true;
3421
+ this.dispatchEvent(new CustomEvent("sp-open", { bubbles: true }));
3422
+ }
3423
+ close() {
3424
+ if (!this.open) {
3425
+ return;
3426
+ }
3427
+ this.open = false;
3428
+ this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
3429
+ }
3430
+ get sidebarClasses() {
3431
+ return getSidebarClasses({ bordered: this.bordered ?? false });
3432
+ }
3433
+ render() {
3434
+ return html`<button
3435
+ aria-expanded="${this.open ? "true" : "false"}"
3436
+ aria-label="${ifDefined(this.toggleLabel)}"
3437
+ class="${getSidebarToggleClasses()}"
3438
+ data-sp-sidebar-toggle
3439
+ type="button"
3440
+ @click="${() => this.toggle()}"
3441
+ >
3442
+ &#9776;
3443
+ </button>
3444
+ <div
3445
+ class="${getSidebarBackdropClasses()}"
3446
+ data-sp-sidebar-backdrop
3447
+ @click="${() => this.close()}"
3448
+ ></div>
3449
+ <aside
3450
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
3451
+ class="${this.sidebarClasses}"
3452
+ data-sp-sidebar-native
3453
+ id="${ifDefined(this.id || void 0)}"
3454
+ title="${ifDefined(this.title || void 0)}"
3455
+ >
3456
+ ${this.hasProjectedContent ? this.projectedContent : nothing}
3457
+ </aside>`;
3458
+ }
3459
+ };
3460
+ SpectreSidebarElement.properties = {
3461
+ bordered: { type: Boolean, reflect: true },
3462
+ open: { type: Boolean, reflect: false },
3463
+ toggleLabel: { attribute: "toggle-label", type: String }
3464
+ };
3465
+ function defineSpectreSidebar(tagName = "sp-sidebar") {
3466
+ const existingElement = customElements.get(tagName);
3467
+ if (existingElement) {
3468
+ return existingElement;
3469
+ }
3470
+ customElements.define(tagName, SpectreSidebarElement);
3471
+ return SpectreSidebarElement;
3472
+ }
3473
+ var SpectreToastElement = class extends SpectreBaseElement {
3474
+ constructor() {
3475
+ super(...arguments);
3476
+ this.dismissed = false;
3477
+ this.fullWidth = false;
3478
+ this.variant = "info";
3479
+ this.iconContent = [];
3480
+ this.bodyContent = [];
3481
+ }
3482
+ get id() {
3483
+ return super.id;
3484
+ }
3485
+ set id(value) {
3486
+ super.id = value;
3487
+ }
3488
+ get title() {
3489
+ return super.title;
3490
+ }
3491
+ set title(value) {
3492
+ super.title = value;
3493
+ }
3494
+ isInternalNode(node) {
3495
+ if (node.nodeType !== Node.ELEMENT_NODE) {
3496
+ return false;
3497
+ }
3498
+ const el = node;
3499
+ return el.hasAttribute("data-sp-toast-native") || el.hasAttribute("data-sp-toast-icon");
3500
+ }
3501
+ syncProjectedContent() {
3502
+ const nextIconContent = [];
3503
+ const nextBodyContent = [];
3504
+ this.childNodes.forEach((node) => {
3505
+ if (this.isInternalNode(node)) {
3506
+ return;
3507
+ }
3508
+ const isIconSlot = node.nodeType === Node.ELEMENT_NODE && node.getAttribute("slot") === "icon";
3509
+ if (isIconSlot) {
3510
+ nextIconContent.push(node);
3511
+ } else {
3512
+ nextBodyContent.push(node);
3513
+ }
3514
+ });
3515
+ const changed = nextIconContent.length !== this.iconContent.length || nextIconContent.some((n, i) => n !== this.iconContent[i]) || nextBodyContent.length !== this.bodyContent.length || nextBodyContent.some((n, i) => n !== this.bodyContent[i]);
3516
+ if (changed) {
3517
+ this.iconContent = nextIconContent;
3518
+ this.bodyContent = nextBodyContent;
3519
+ }
3520
+ return changed;
3521
+ }
3522
+ get hasIconContent() {
3523
+ return hasMeaningfulContent(this.iconContent);
3524
+ }
3525
+ get hasBodyContent() {
3526
+ return hasMeaningfulContent(this.bodyContent);
3527
+ }
3528
+ connectedCallback() {
3529
+ super.connectedCallback();
3530
+ this.syncProjectedContent();
3531
+ this.startContentObserver();
3532
+ }
3533
+ disconnectedCallback() {
3534
+ this.stopContentObserver();
3535
+ this.clearAutoDismissTimer();
3536
+ super.disconnectedCallback();
3537
+ }
3538
+ update(changedProperties) {
3539
+ this.stopContentObserver();
3540
+ super.update(changedProperties);
3541
+ this.startContentObserver();
3542
+ }
3543
+ startContentObserver() {
3544
+ if (this.contentObserver) {
3545
+ return;
3546
+ }
3547
+ this.contentObserver = new MutationObserver(() => {
3548
+ if (this.syncProjectedContent()) {
3549
+ this.requestUpdate();
3550
+ }
3551
+ });
3552
+ this.contentObserver.observe(this, { childList: true });
3553
+ }
3554
+ stopContentObserver() {
3555
+ this.contentObserver?.disconnect();
3556
+ this.contentObserver = void 0;
3557
+ }
3558
+ willUpdate(changedProperties) {
3559
+ if (changedProperties.has("dismissed") && this.dismissed == null) {
3560
+ this.dismissed = false;
3561
+ }
3562
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3563
+ this.fullWidth = false;
3564
+ }
3565
+ if (changedProperties.has("variant") && (this.variant == null || !isToastVariant(this.variant))) {
3566
+ this.variant = "info";
3567
+ }
3568
+ if (changedProperties.has("autoDismiss")) {
3569
+ this.autoDismiss = normalizeInt(this.autoDismiss, void 0, 0);
3570
+ }
3571
+ }
3572
+ updated(changedProperties) {
3573
+ super.updated(changedProperties);
3574
+ if (changedProperties.has("dismissed") || changedProperties.has("autoDismiss")) {
3575
+ this.clearAutoDismissTimer();
3576
+ if (!this.dismissed && this.autoDismiss) {
3577
+ this.autoDismissTimer = setTimeout(() => {
3578
+ this.dismiss();
3579
+ }, this.autoDismiss);
3580
+ }
3581
+ }
3582
+ }
3583
+ clearAutoDismissTimer() {
3584
+ if (this.autoDismissTimer) {
3585
+ clearTimeout(this.autoDismissTimer);
3586
+ this.autoDismissTimer = void 0;
3587
+ }
3588
+ }
3589
+ show() {
3590
+ if (!this.dismissed) {
3591
+ return;
3592
+ }
3593
+ this.dismissed = false;
3594
+ this.dispatchEvent(new CustomEvent("sp-show", { bubbles: true }));
3595
+ }
3596
+ dismiss() {
3597
+ if (this.dismissed) {
3598
+ return;
3599
+ }
3600
+ this.dismissed = true;
3601
+ this.dispatchEvent(new CustomEvent("sp-dismiss", { bubbles: true }));
3602
+ }
3603
+ get toastClasses() {
3604
+ return getToastClasses({
3605
+ variant: this.variant,
3606
+ dismissed: this.dismissed ?? false,
3607
+ fullWidth: this.fullWidth ?? false
3608
+ });
3609
+ }
3610
+ get iconClasses() {
3611
+ return getToastIconClasses({ variant: this.variant });
3612
+ }
3613
+ render() {
3614
+ return html`<div
3615
+ aria-atomic="true"
3616
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
3617
+ aria-live="polite"
3618
+ class="${this.toastClasses}"
3619
+ data-sp-toast-native
3620
+ id="${ifDefined(this.id || void 0)}"
3621
+ role="status"
3622
+ title="${ifDefined(this.title || void 0)}"
3623
+ >
3624
+ ${this.hasIconContent ? html`<div class="${this.iconClasses}" data-sp-toast-icon>
3625
+ ${this.iconContent}
3626
+ </div>` : nothing}
3627
+ ${this.hasBodyContent ? this.bodyContent : nothing}
3628
+ </div>`;
3629
+ }
3630
+ };
3631
+ SpectreToastElement.properties = {
3632
+ autoDismiss: { attribute: "auto-dismiss", type: Number },
3633
+ dismissed: { type: Boolean, reflect: true },
3634
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3635
+ variant: { type: String, reflect: true }
3636
+ };
3637
+ function defineSpectreToast(tagName = "sp-toast") {
3638
+ const existingElement = customElements.get(tagName);
3639
+ if (existingElement) {
3640
+ return existingElement;
3641
+ }
3642
+ customElements.define(tagName, SpectreToastElement);
3643
+ return SpectreToastElement;
3644
+ }
3645
+ var SpectreTooltipElement = class extends SpectreBaseElement {
3646
+ constructor() {
3647
+ super(...arguments);
3648
+ this.placement = "top";
3649
+ this.visible = false;
3650
+ this.triggerContent = [];
3651
+ this.tooltipContent = [];
3652
+ }
3653
+ get id() {
3654
+ return super.id;
3655
+ }
3656
+ set id(value) {
3657
+ super.id = value;
3658
+ }
3659
+ get title() {
3660
+ return super.title;
3661
+ }
3662
+ set title(value) {
3663
+ super.title = value;
3664
+ }
3665
+ isInternalNode(node) {
3666
+ if (node.nodeType !== Node.ELEMENT_NODE) {
3667
+ return false;
3668
+ }
3669
+ const el = node;
3670
+ return el.hasAttribute("data-sp-tooltip-native") || el.hasAttribute("data-sp-tooltip-trigger");
3671
+ }
3672
+ syncProjectedContent() {
3673
+ const nextTooltipContent = [];
3674
+ const nextTriggerContent = [];
3675
+ this.childNodes.forEach((node) => {
3676
+ if (this.isInternalNode(node)) {
3677
+ return;
3678
+ }
3679
+ const isTooltipSlot = node.nodeType === Node.ELEMENT_NODE && node.getAttribute("slot") === "tooltip";
3680
+ if (isTooltipSlot) {
3681
+ nextTooltipContent.push(node);
3682
+ } else {
3683
+ nextTriggerContent.push(node);
3684
+ }
3685
+ });
3686
+ const changed = nextTooltipContent.length !== this.tooltipContent.length || nextTooltipContent.some((n, i) => n !== this.tooltipContent[i]) || nextTriggerContent.length !== this.triggerContent.length || nextTriggerContent.some((n, i) => n !== this.triggerContent[i]);
3687
+ if (changed) {
3688
+ this.tooltipContent = nextTooltipContent;
3689
+ this.triggerContent = nextTriggerContent;
3690
+ }
3691
+ return changed;
3692
+ }
3693
+ get hasTooltipContent() {
3694
+ return hasMeaningfulContent(this.tooltipContent);
3695
+ }
3696
+ connectedCallback() {
3697
+ var _a, _b;
3698
+ super.connectedCallback();
3699
+ this.syncProjectedContent();
3700
+ this.startContentObserver();
3701
+ (_a = this.style).position || (_a.position = "relative");
3702
+ (_b = this.style).display || (_b.display = "inline-block");
3703
+ }
3704
+ disconnectedCallback() {
3705
+ this.stopContentObserver();
3706
+ super.disconnectedCallback();
3707
+ }
3708
+ update(changedProperties) {
3709
+ this.stopContentObserver();
3710
+ super.update(changedProperties);
3711
+ this.startContentObserver();
3712
+ }
3713
+ startContentObserver() {
3714
+ if (this.contentObserver) {
3715
+ return;
3716
+ }
3717
+ this.contentObserver = new MutationObserver(() => {
3718
+ if (this.syncProjectedContent()) {
3719
+ this.requestUpdate();
3720
+ }
3721
+ });
3722
+ this.contentObserver.observe(this, { childList: true });
3723
+ }
3724
+ stopContentObserver() {
3725
+ this.contentObserver?.disconnect();
3726
+ this.contentObserver = void 0;
3727
+ }
3728
+ willUpdate(changedProperties) {
3729
+ if (changedProperties.has("placement") && (this.placement == null || !isTooltipPlacement(this.placement))) {
3730
+ this.placement = "top";
3731
+ }
3732
+ if (changedProperties.has("visible") && this.visible == null) {
3733
+ this.visible = false;
3734
+ }
3735
+ }
3736
+ show() {
3737
+ if (this.visible) {
3738
+ return;
3739
+ }
3740
+ this.visible = true;
3741
+ this.dispatchEvent(new CustomEvent("sp-show", { bubbles: true }));
3742
+ }
3743
+ hide() {
3744
+ if (!this.visible) {
3745
+ return;
3746
+ }
3747
+ this.visible = false;
3748
+ this.dispatchEvent(new CustomEvent("sp-hide", { bubbles: true }));
3749
+ }
3750
+ get tooltipClasses() {
3751
+ return getTooltipClasses({
3752
+ placement: this.placement,
3753
+ visible: this.visible ?? false
3754
+ });
3755
+ }
3756
+ render() {
3757
+ return html`<span
3758
+ data-sp-tooltip-trigger
3759
+ @focusin="${() => this.show()}"
3760
+ @focusout="${() => this.hide()}"
3761
+ @mouseenter="${() => this.show()}"
3762
+ @mouseleave="${() => this.hide()}"
3763
+ >
3764
+ ${this.triggerContent}
3765
+ </span>
3766
+ <span
3767
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
3768
+ class="${this.tooltipClasses}"
3769
+ data-sp-tooltip-native
3770
+ id="${ifDefined(this.id || void 0)}"
3771
+ role="tooltip"
3772
+ title="${ifDefined(this.title || void 0)}"
3773
+ >
3774
+ ${this.hasTooltipContent ? this.tooltipContent : nothing}
3775
+ </span>`;
3776
+ }
3777
+ };
3778
+ SpectreTooltipElement.properties = {
3779
+ placement: { type: String, reflect: true },
3780
+ visible: { type: Boolean, reflect: true }
3781
+ };
3782
+ function defineSpectreTooltip(tagName = "sp-tooltip") {
3783
+ const existingElement = customElements.get(tagName);
3784
+ if (existingElement) {
3785
+ return existingElement;
3786
+ }
3787
+ customElements.define(tagName, SpectreTooltipElement);
3788
+ return SpectreTooltipElement;
3789
+ }
2887
3790
 
2888
3791
  // src/index.ts
2889
3792
  function defineSpectreComponents() {
@@ -2909,8 +3812,14 @@ function defineSpectreComponents() {
2909
3812
  defineSpectreGrid();
2910
3813
  defineSpectreSection();
2911
3814
  defineSpectreStack();
3815
+ defineSpectreDropdown();
3816
+ defineSpectreModal();
3817
+ defineSpectreNav();
3818
+ defineSpectreSidebar();
3819
+ defineSpectreToast();
3820
+ defineSpectreTooltip();
2912
3821
  }
2913
3822
 
2914
- export { SpectreAlertElement, SpectreAvatarElement, SpectreBadgeElement, SpectreButtonElement, SpectreCardElement, SpectreCheckboxElement, SpectreContainerElement, SpectreFieldsetElement, SpectreGridElement, SpectreIconBoxElement, SpectreInputElement, SpectreLabelElement, SpectrePricingCardElement, SpectreRadioElement, SpectreRatingElement, SpectreSectionElement, SpectreSelectElement, SpectreSpinnerElement, SpectreStackElement, SpectreTagElement, SpectreTestimonialElement, SpectreTextareaElement, defineSpectreAlert, defineSpectreAvatar, defineSpectreBadge, defineSpectreButton, defineSpectreCard, defineSpectreCheckbox, defineSpectreComponents, defineSpectreContainer, defineSpectreFieldset, defineSpectreGrid, defineSpectreIconBox, defineSpectreInput, defineSpectreLabel, defineSpectrePricingCard, defineSpectreRadio, defineSpectreRating, defineSpectreSection, defineSpectreSelect, defineSpectreSpinner, defineSpectreStack, defineSpectreTag, defineSpectreTestimonial, defineSpectreTextarea, spectreInputSizes as spectreAlertSizes, spectreAlertVariants, spectreAvatarShapes, spectreAvatarSizes, spectreInputSizes as spectreBadgeSizes, spectreBadgeVariants, spectreInputSizes as spectreButtonSizes, spectreButtonTypes, spectreButtonVariants, spectreCardVariants, spectreContainerMaxWidths, spectreGridColumns, spectreGridGaps, spectreInputSizes as spectreIconBoxSizes, spectreIconBoxVariants, spectreInputSizes, spectreInputTypes, spectreInputSizes as spectreRatingSizes, spectreInputSizes as spectreSpinnerSizes, spectreSpinnerVariants, spectreStackAligns, spectreStackBases, spectreStackDirections, spectreInputSizes as spectreTagSizes, spectreTagVariants, spectreTestimonialVariants };
3823
+ export { SpectreAlertElement, SpectreAvatarElement, SpectreBadgeElement, SpectreButtonElement, SpectreCardElement, SpectreCheckboxElement, SpectreContainerElement, SpectreDropdownElement, SpectreFieldsetElement, SpectreGridElement, SpectreIconBoxElement, SpectreInputElement, SpectreLabelElement, SpectreModalElement, SpectreNavElement, SpectrePricingCardElement, SpectreRadioElement, SpectreRatingElement, SpectreSectionElement, SpectreSelectElement, SpectreSidebarElement, SpectreSpinnerElement, SpectreStackElement, SpectreTagElement, SpectreTestimonialElement, SpectreTextareaElement, SpectreToastElement, SpectreTooltipElement, defineSpectreAlert, defineSpectreAvatar, defineSpectreBadge, defineSpectreButton, defineSpectreCard, defineSpectreCheckbox, defineSpectreComponents, defineSpectreContainer, defineSpectreDropdown, defineSpectreFieldset, defineSpectreGrid, defineSpectreIconBox, defineSpectreInput, defineSpectreLabel, defineSpectreModal, defineSpectreNav, defineSpectrePricingCard, defineSpectreRadio, defineSpectreRating, defineSpectreSection, defineSpectreSelect, defineSpectreSidebar, defineSpectreSpinner, defineSpectreStack, defineSpectreTag, defineSpectreTestimonial, defineSpectreTextarea, defineSpectreToast, defineSpectreTooltip, spectreInputSizes as spectreAlertSizes, spectreAlertVariants, spectreAvatarShapes, spectreAvatarSizes, spectreInputSizes as spectreBadgeSizes, spectreBadgeVariants, spectreInputSizes as spectreButtonSizes, spectreButtonTypes, spectreButtonVariants, spectreCardVariants, spectreContainerMaxWidths, spectreDropdownPlacements, spectreGridColumns, spectreGridGaps, spectreInputSizes as spectreIconBoxSizes, spectreIconBoxVariants, spectreInputSizes, spectreInputTypes, spectreInputSizes as spectreRatingSizes, spectreInputSizes as spectreSpinnerSizes, spectreSpinnerVariants, spectreStackAligns, spectreStackBases, spectreStackDirections, spectreInputSizes as spectreTagSizes, spectreTagVariants, spectreTestimonialVariants, spectreToastVariants, spectreTooltipPlacements };
2915
3824
  //# sourceMappingURL=index.js.map
2916
3825
  //# sourceMappingURL=index.js.map