@orange-halo/components 2.2.0 → 3.1.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 (140) hide show
  1. package/custom-elements.json +565 -328
  2. package/dist/base.d.ts.map +1 -1
  3. package/dist/base.js +7 -0
  4. package/dist/base.js.map +1 -1
  5. package/dist/index.d.ts +2 -7
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -4
  8. package/dist/index.js.map +1 -1
  9. package/dist/oh-accordion.d.ts +53 -8
  10. package/dist/oh-accordion.d.ts.map +1 -1
  11. package/dist/oh-accordion.js +83 -21
  12. package/dist/oh-accordion.js.map +1 -1
  13. package/dist/oh-alert.d.ts +26 -8
  14. package/dist/oh-alert.d.ts.map +1 -1
  15. package/dist/oh-alert.js +32 -14
  16. package/dist/oh-alert.js.map +1 -1
  17. package/dist/oh-badge.d.ts +32 -13
  18. package/dist/oh-badge.d.ts.map +1 -1
  19. package/dist/oh-badge.js +35 -16
  20. package/dist/oh-badge.js.map +1 -1
  21. package/dist/oh-breadcrumb.d.ts +39 -12
  22. package/dist/oh-breadcrumb.d.ts.map +1 -1
  23. package/dist/oh-breadcrumb.js +43 -21
  24. package/dist/oh-breadcrumb.js.map +1 -1
  25. package/dist/oh-button.d.ts +50 -24
  26. package/dist/oh-button.d.ts.map +1 -1
  27. package/dist/oh-button.js +66 -47
  28. package/dist/oh-button.js.map +1 -1
  29. package/dist/oh-card.d.ts +47 -19
  30. package/dist/oh-card.d.ts.map +1 -1
  31. package/dist/oh-card.js +110 -82
  32. package/dist/oh-card.js.map +1 -1
  33. package/dist/oh-checkbox-group.d.ts +56 -12
  34. package/dist/oh-checkbox-group.d.ts.map +1 -1
  35. package/dist/oh-checkbox-group.js +87 -45
  36. package/dist/oh-checkbox-group.js.map +1 -1
  37. package/dist/oh-checkbox.d.ts +55 -18
  38. package/dist/oh-checkbox.d.ts.map +1 -1
  39. package/dist/oh-checkbox.js +91 -59
  40. package/dist/oh-checkbox.js.map +1 -1
  41. package/dist/oh-cluster.d.ts +19 -14
  42. package/dist/oh-cluster.d.ts.map +1 -1
  43. package/dist/oh-cluster.js +19 -19
  44. package/dist/oh-cluster.js.map +1 -1
  45. package/dist/oh-container.d.ts +19 -16
  46. package/dist/oh-container.d.ts.map +1 -1
  47. package/dist/oh-container.js +26 -33
  48. package/dist/oh-container.js.map +1 -1
  49. package/dist/oh-drawer.d.ts +36 -14
  50. package/dist/oh-drawer.d.ts.map +1 -1
  51. package/dist/oh-drawer.js +57 -26
  52. package/dist/oh-drawer.js.map +1 -1
  53. package/dist/oh-footer.d.ts +37 -18
  54. package/dist/oh-footer.d.ts.map +1 -1
  55. package/dist/oh-footer.js +38 -19
  56. package/dist/oh-footer.js.map +1 -1
  57. package/dist/oh-grid.d.ts +27 -14
  58. package/dist/oh-grid.d.ts.map +1 -1
  59. package/dist/oh-grid.js +27 -19
  60. package/dist/oh-grid.js.map +1 -1
  61. package/dist/oh-icon.d.ts +21 -5
  62. package/dist/oh-icon.d.ts.map +1 -1
  63. package/dist/oh-icon.js +28 -5
  64. package/dist/oh-icon.js.map +1 -1
  65. package/dist/oh-input.d.ts +105 -21
  66. package/dist/oh-input.d.ts.map +1 -1
  67. package/dist/oh-input.js +207 -68
  68. package/dist/oh-input.js.map +1 -1
  69. package/dist/oh-link.d.ts +42 -19
  70. package/dist/oh-link.d.ts.map +1 -1
  71. package/dist/oh-link.js +56 -34
  72. package/dist/oh-link.js.map +1 -1
  73. package/dist/oh-modal.d.ts +29 -6
  74. package/dist/oh-modal.d.ts.map +1 -1
  75. package/dist/oh-modal.js +37 -16
  76. package/dist/oh-modal.js.map +1 -1
  77. package/dist/oh-navbar.d.ts +42 -19
  78. package/dist/oh-navbar.d.ts.map +1 -1
  79. package/dist/oh-navbar.js +44 -21
  80. package/dist/oh-navbar.js.map +1 -1
  81. package/dist/oh-progress.d.ts +26 -7
  82. package/dist/oh-progress.d.ts.map +1 -1
  83. package/dist/oh-progress.js +32 -13
  84. package/dist/oh-progress.js.map +1 -1
  85. package/dist/oh-radio-group.d.ts +55 -13
  86. package/dist/oh-radio-group.d.ts.map +1 -1
  87. package/dist/oh-radio-group.js +84 -44
  88. package/dist/oh-radio-group.js.map +1 -1
  89. package/dist/oh-radio.d.ts +56 -18
  90. package/dist/oh-radio.d.ts.map +1 -1
  91. package/dist/oh-radio.js +93 -60
  92. package/dist/oh-radio.js.map +1 -1
  93. package/dist/oh-select.d.ts +58 -16
  94. package/dist/oh-select.d.ts.map +1 -1
  95. package/dist/oh-select.js +72 -36
  96. package/dist/oh-select.js.map +1 -1
  97. package/dist/oh-skip-link.d.ts +33 -15
  98. package/dist/oh-skip-link.d.ts.map +1 -1
  99. package/dist/oh-skip-link.js +39 -26
  100. package/dist/oh-skip-link.js.map +1 -1
  101. package/dist/oh-stack.d.ts +17 -14
  102. package/dist/oh-stack.d.ts.map +1 -1
  103. package/dist/oh-stack.js +18 -20
  104. package/dist/oh-stack.js.map +1 -1
  105. package/dist/oh-tabs.d.ts +56 -30
  106. package/dist/oh-tabs.d.ts.map +1 -1
  107. package/dist/oh-tabs.js +89 -70
  108. package/dist/oh-tabs.js.map +1 -1
  109. package/dist/oh-textarea.d.ts +37 -6
  110. package/dist/oh-textarea.d.ts.map +1 -1
  111. package/dist/oh-textarea.js +40 -9
  112. package/dist/oh-textarea.js.map +1 -1
  113. package/dist/oh-toggle.d.ts +45 -12
  114. package/dist/oh-toggle.d.ts.map +1 -1
  115. package/dist/oh-toggle.js +68 -33
  116. package/dist/oh-toggle.js.map +1 -1
  117. package/dist/styles/typography.d.ts.map +1 -1
  118. package/dist/styles/typography.js +1 -2
  119. package/dist/styles/typography.js.map +1 -1
  120. package/package.json +3 -7
  121. package/dist/oh-button.figma.d.ts +0 -2
  122. package/dist/oh-button.figma.d.ts.map +0 -1
  123. package/dist/oh-button.figma.js +0 -18
  124. package/dist/oh-button.figma.js.map +0 -1
  125. package/dist/oh-checkbox-group.figma.d.ts +0 -2
  126. package/dist/oh-checkbox-group.figma.d.ts.map +0 -1
  127. package/dist/oh-checkbox-group.figma.js +0 -24
  128. package/dist/oh-checkbox-group.figma.js.map +0 -1
  129. package/dist/oh-hero.d.ts +0 -33
  130. package/dist/oh-hero.d.ts.map +0 -1
  131. package/dist/oh-hero.js +0 -248
  132. package/dist/oh-hero.js.map +0 -1
  133. package/dist/oh-input.figma.d.ts +0 -2
  134. package/dist/oh-input.figma.d.ts.map +0 -1
  135. package/dist/oh-input.figma.js +0 -36
  136. package/dist/oh-input.figma.js.map +0 -1
  137. package/dist/oh-radio-group.figma.d.ts +0 -2
  138. package/dist/oh-radio-group.figma.d.ts.map +0 -1
  139. package/dist/oh-radio-group.figma.js +0 -22
  140. package/dist/oh-radio-group.figma.js.map +0 -1
package/dist/oh-button.js CHANGED
@@ -1,32 +1,23 @@
1
1
  /**
2
2
  * oh-button
3
3
  *
4
- * A chunky, confident button with playful personality.
5
- * Inspired by hand-crafted, illustrative UI — not corporate SaaS.
6
- *
7
4
  * DESIGN DECISIONS:
8
5
  * ─────────────────
9
- * 1. CHUNKY & CONFIDENT
10
- * - Thick border (stroke.control) that feels illustrative
11
- * - Solid fills, no subtle gradients
12
- * - Generous padding, substantial presence
13
- *
14
- * 2. OFFSET SHADOW (STICKER EFFECT)
15
- * - Shadow offset to bottom-right
16
- * - Feels like a physical sticker or stamp
17
- * - Not a generic centered drop shadow
18
- *
19
- * 3. PLAYFUL INTERACTIONS
20
- * - Hover: slight upward lift + shadow grows
21
- * - Active: pressed down, shadow shrinks (stamp effect)
22
- * - Focus: warm glow + accessible underline
23
- *
24
- * 4. HAND-CRAFTED FEEL
25
- * - Bold, defined edges
26
- * - Confident color choices
27
- * - Personality over polish
28
- *
29
- * @element oh-button
6
+ * 1. Renders a native <button>, or an <a> when `href` is set, inside the
7
+ * shadow root, so keyboard and screen reader behaviour come from the
8
+ * platform. `accessible-label` is forwarded to it (an aria-label on the
9
+ * host isn't).
10
+ * 2. Look comes from button.* component tokens: button.base.borderWidth
11
+ * (stroke.control), button.base.borderRadius (shape.control),
12
+ * button.variant.<variant>.* for fills, text, border and shadow colour,
13
+ * button.size.<size>.* for type, padding and height.
14
+ * 3. Hover and active move the button by lift.hoverMd / lift.pressMd and set
15
+ * the shadow offset to elevation.offset.2xl / elevation.offset.xs (rest is
16
+ * elevation.offset.lg).
17
+ * 4. Focus is a solid underline on the label (an underline the button draws
18
+ * itself for icon-only and loading buttons, whose text is hidden).
19
+ * 5. Loading uses aria-disabled + aria-busy, not disabled, so focus stays on
20
+ * the button.
30
21
  */
31
22
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
32
23
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -37,6 +28,41 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
37
28
  import { html, css, nothing } from "lit";
38
29
  import { customElement, property } from "lit/decorators.js";
39
30
  import { OhElement, baseStyles } from "./base.js";
31
+ /**
32
+ * A button that starts an action, or a link styled as a button when `href` is set.
33
+ *
34
+ * **Use it for** actions: submitting, saving, opening a dialog, confirming.
35
+ * **Don't use it for** links inside running text (use `oh-link`).
36
+ *
37
+ * **Variants:** `primary` for the main action, `secondary` for the others,
38
+ * `accent` for an action that takes the accent colour role. **Sizes:** `sm`, `md` (default), `lg`.
39
+ * **States:** rest, hover, active, focus and `loading`.
40
+ *
41
+ * **Behaviour:** fires `oh-click` when the inner `<button>` is clicked, except
42
+ * while `loading`. `loading` shows a spinner, keeps the label for screen
43
+ * readers, sets `aria-busy` and `aria-disabled` and ignores clicks, while the
44
+ * button stays focusable. With `href` it renders an `<a>` (and
45
+ * `target="_blank"` adds `rel="noopener noreferrer"`); link buttons don't fire
46
+ * `oh-click`. It has no `disabled` property and doesn't submit a form by
47
+ * itself: handle `oh-click`. Under `prefers-reduced-motion` it doesn't move.
48
+ *
49
+ * **Accessibility:** focus shows a solid underline on the label. An
50
+ * `icon-only` button has no visible text, so always set `accessible-label`
51
+ * (not `aria-label`, which isn't forwarded into the shadow root).
52
+ *
53
+ * **Look:** set by tokens — `stroke.control` (border width), `shape.control`
54
+ * (corners), `typography.control.*` (type), `button.variant.<variant>.*`
55
+ * (background, text, border and shadow colour per state), `button.size.<size>.*`
56
+ * (font size, padding, minimum height), `elevation.offset.*` (shadow offset)
57
+ * and `lift.hoverMd` / `lift.pressMd` (movement on hover and press).
58
+ *
59
+ * @element oh-button
60
+ * @fires oh-click - The button was clicked (not while loading). `detail.originalEvent` is the click.
61
+ * @slot - The label.
62
+ * @slot icon-left - An icon before the label.
63
+ * @slot icon-right - An icon after the label.
64
+ * @csspart button - The inner `<button>` or `<a>`.
65
+ */
40
66
  let OhButton = class OhButton extends OhElement {
41
67
  constructor() {
42
68
  super(...arguments);
@@ -45,7 +71,7 @@ let OhButton = class OhButton extends OhElement {
45
71
  this.loading = false;
46
72
  this.iconOnly = false;
47
73
  /**
48
- * Force a visual state (for documentation/Figma sync only)
74
+ * Force a visual state (for documentation only)
49
75
  * Values: 'hover' | 'active' | 'focus'
50
76
  */
51
77
  this.forceState = "default";
@@ -53,17 +79,12 @@ let OhButton = class OhButton extends OhElement {
53
79
  static { this.styles = [
54
80
  baseStyles,
55
81
  css `
56
- /* ═══════════════════════════════════════════════════════════════
57
- ORANGE HALO BUTTON
58
- Chunky • Playful • Confident • Hand-crafted
59
- ═══════════════════════════════════════════════════════════════ */
60
-
61
82
  :host {
62
83
  display: inline-block;
63
84
  }
64
85
 
65
86
  .button {
66
- /* Typography: friendly, not shouty */
87
+ /* Typography: button.base.* (from typography.control.*) */
67
88
  font-family: var(--oh-button-base-font-family);
68
89
  font-weight: var(--oh-button-base-font-weight);
69
90
  letter-spacing: var(--oh-button-base-letter-spacing);
@@ -75,10 +96,10 @@ let OhButton = class OhButton extends OhElement {
75
96
  justify-content: center;
76
97
  gap: var(--oh-spacing-2);
77
98
 
78
- /* Shape: chunky rounded corners, not pills */
99
+ /* Corners: button.base.borderRadius (shape.control) */
79
100
  border-radius: var(--oh-button-base-border-radius);
80
101
 
81
- /* Thick illustrative border */
102
+ /* Border width: button.base.borderWidth (stroke.control) */
82
103
  border: var(--oh-button-base-border-width) solid;
83
104
 
84
105
  /* Remove default button styles */
@@ -87,18 +108,16 @@ let OhButton = class OhButton extends OhElement {
87
108
  -moz-appearance: none;
88
109
  appearance: none;
89
110
 
90
- /* Smooth but snappy transitions */
111
+ /* Transitions: motion.snappy / motion.quick */
91
112
  transition:
92
- transform var(--oh-motion-snappy) var(--oh-motion-ease-playful),
93
- box-shadow var(--oh-motion-snappy) var(--oh-motion-ease-playful),
113
+ transform var(--oh-motion-snappy) var(--oh-motion-ease-emphasized),
114
+ box-shadow var(--oh-motion-snappy) var(--oh-motion-ease-emphasized),
94
115
  background-color var(--oh-motion-quick) ease;
95
116
  }
96
117
 
97
118
  /* ═══════════════════════════════════════════════════════════════
98
119
  PRIMARY VARIANT
99
- Signature orange — bold and warm
100
- Filled button: color + shadow define shape (no visible border)
101
- Contrast: white on brand primary = 5.0:1 ✓ (WCAG AA)
120
+ Filled: button.variant.primary.* (border matches the fill)
102
121
  ═══════════════════════════════════════════════════════════════ */
103
122
 
104
123
  .button--primary {
@@ -106,7 +125,7 @@ let OhButton = class OhButton extends OhElement {
106
125
  border-color: var(--oh-button-variant-primary-border-color);
107
126
  color: var(--oh-button-variant-primary-color);
108
127
 
109
- /* Light offset shadow: makes button pop forward */
128
+ /* Offset shadow: elevation.offset.lg at rest */
110
129
  box-shadow: var(--oh-elevation-offset-lg) var(--oh-elevation-offset-lg)
111
130
  0 0 var(--oh-button-variant-primary-shadow-color);
112
131
  }
@@ -130,7 +149,8 @@ let OhButton = class OhButton extends OhElement {
130
149
 
131
150
  /* ═══════════════════════════════════════════════════════════════
132
151
  SECONDARY VARIANT
133
- Light button: NEEDS visible border for definition
152
+ button.variant.secondary.*: its border (borderColor) defines the
153
+ button's edge against the page, so it must stay visible
134
154
  ═══════════════════════════════════════════════════════════════ */
135
155
 
136
156
  .button--secondary {
@@ -159,8 +179,7 @@ let OhButton = class OhButton extends OhElement {
159
179
 
160
180
  /* ═══════════════════════════════════════════════════════════════
161
181
  ACCENT VARIANT
162
- Calm blue — modern counterbalance to warm orange
163
- Filled button: color + shadow define shape (no visible border)
182
+ Filled: button.variant.accent.* (border matches the fill)
164
183
  ═══════════════════════════════════════════════════════════════ */
165
184
 
166
185
  .button--accent {
@@ -217,8 +236,8 @@ let OhButton = class OhButton extends OhElement {
217
236
 
218
237
  /* ═══════════════════════════════════════════════════════════════
219
238
  SIZE VARIANTS
220
- Minimum 16px (1rem) for WCAG readability
221
- Values: button.size.* tokens
239
+ Values: button.size.* tokens. Font sizes come from
240
+ typography.control.fontSize.*, never below font.size.base
222
241
  ═══════════════════════════════════════════════════════════════ */
223
242
 
224
243
  .button--sm {
@@ -289,7 +308,7 @@ let OhButton = class OhButton extends OhElement {
289
308
  content: "";
290
309
  position: absolute;
291
310
  bottom: 4px;
292
- left: 50%;
311
+ left: 50%; /* physical: centred, with the translate below */
293
312
  transform: translateX(-50%);
294
313
  width: 60%;
295
314
  height: 2px;
@@ -363,7 +382,7 @@ let OhButton = class OhButton extends OhElement {
363
382
  }
364
383
 
365
384
  /* ═══════════════════════════════════════════════════════════════
366
- FORCED STATES (for Figma Sync / documentation)
385
+ FORCED STATES (for documentation)
367
386
  ═══════════════════════════════════════════════════════════════ */
368
387
 
369
388
  /* Primary - Forced Hover */
@@ -1 +1 @@
1
- {"version":3,"file":"oh-button.js","sourceRoot":"","sources":["../src/oh-button.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oh-button.js","sourceRoot":"","sources":["../src/oh-button.ts"],"names":[],"mappings":"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"}
package/dist/oh-card.d.ts CHANGED
@@ -1,37 +1,65 @@
1
1
  /**
2
2
  * oh-card
3
3
  *
4
- * A tactile, raised surface with visible frame.
5
- * Designed with the same layered construction as oh-button.
4
+ * A surface that groups related content, with optional header and footer.
6
5
  *
7
6
  * DESIGN DECISIONS:
8
7
  * ─────────────────
9
- * 1. LAYERED CONSTRUCTION
10
- * - Surface: subtle gradient for depth
11
- * - Border: visible warm edge
12
- * - Inner highlight: sunlit top edge
13
- * - Outer shadow: soft, slightly offset
14
- *
15
- * 2. RETRO-MODERN DETAILS
16
- * - Warm, tactile shadows (never harsh)
17
- * - Visible border that warms on hover
18
- * - Subtle gradient background
19
- *
20
- * 3. VARIANTS
21
- * - Raised: default with layered depth
22
- * - Sunlit: featured with warm gradient
23
- * - Flat: border-only, minimal shadow
8
+ * 1. THREE PARTS: header, content and footer are separate parts so each can
9
+ * be styled.
24
10
  *
25
- * @element oh-card
11
+ * 2. VARIANTS BY ROLE, LOOK FROM TOKENS
12
+ * - default, featured (the one card that should stand out), subtle (quieter)
13
+ * - Each variant's surface, border and shadow come from its own
14
+ * card.variant.<variant>.* tokens and an elevation.surface.* token, so a brand
15
+ * changes the look without touching this file.
16
+ *
17
+ * 3. INTERACTIVE MODE: role="button" on the inner card, Enter/Space and
18
+ * click fire oh-click. Focus is a solid focus.ring* outline; any
19
+ * focus.glowColor shadow is decoration only.
20
+ *
21
+ * 4. CONTRAST: card surfaces remap color.text.link to color.text.linkRaised
22
+ * so links inside keep 4.5:1.
26
23
  */
27
24
  import { OhElement } from "./base.js";
28
- export type CardVariant = "raised" | "sunlit" | "flat";
25
+ export type CardVariant = "default" | "featured" | "subtle";
29
26
  export type CardPadding = "none" | "sm" | "md" | "lg";
27
+ /**
28
+ * A surface that groups related content (a summary, a teaser, a settings group), with optional header and footer.
29
+ *
30
+ * **Use it for** a self-contained block of content among others, or a whole-card link to more detail (`interactive`). **Don't use it for** page layout or spacing alone (use `oh-stack`, `oh-grid`); for a message that needs attention (use `oh-alert`); or for a single action (use `oh-button`).
31
+ *
32
+ * **Variants:** `default`, the standard card; `featured`, for the one card that should stand out; `subtle`, a quieter card, for dense layouts. **Padding:** `none`, `sm`, `md` (default), `lg` set the content padding (and the header and footer padding to match). With `none`, the content sets its own padding.
33
+ *
34
+ * **States (interactive only):** rest, hover, active (pressed) and focus-visible.
35
+ *
36
+ * **Behaviour:** with `interactive`, the card is focusable (`tabindex="0"`), has `role="button"`, and fires `oh-click` on click, Enter or Space. Hover movement is turned off under `prefers-reduced-motion`.
37
+ *
38
+ * **Accessibility:** focus shows a solid outline (`focus.ringWidth`, `focus.ringColor`, `focus.ringOffset`). Links inside use `color.text.linkRaised`, which keeps contrast on card surfaces. An interactive card is one button: give it a short heading so its accessible name makes sense, and don't put other buttons or links inside it.
39
+ *
40
+ * **Look:** set by tokens. `card.variant.<variant>.gradientStart`/`gradientMid`/`gradientEnd` set each variant's surface, `card.variant.<variant>.borderColor` and `card.base.borderWidth` its border, `shape.large` the corners, and `elevation.surface.default`/`subtle`/`featured` its shadow. Hover uses `color.border.strong` (or `card.variant.featured.borderColorHover`), `elevation.surface.hover`/`featuredHover` and `lift.hoverMd`/`lift.hoverSm`; active uses `elevation.surface.active`; focus sets the border to `color.brand.primary` and adds `focus.glowColor` with `elevation.surface.focus`/`featuredFocus`. Header and footer dividers use `card.section.dividerColor` and `stroke.divider`; the header surface uses `card.section.headerGradientStart`/`End`, the footer `color.surface.raised` to `color.surface.inset`; motion uses `motion.gentle` and `motion.easeGentle`.
41
+ *
42
+ * @element oh-card
43
+ * @slot - The card's main content.
44
+ * @slot header - Optional header, above the content, with a divider below. Not drawn when nothing is slotted.
45
+ * @slot footer - Optional footer, below the content, with a divider above (e.g. actions). Not drawn when nothing is slotted.
46
+ * @csspart card - The card surface (the button when `interactive`).
47
+ * @csspart header - The header wrapper.
48
+ * @csspart content - The content wrapper.
49
+ * @csspart footer - The footer wrapper.
50
+ * @fires oh-click - When an `interactive` card is clicked or activated with Enter or Space. `detail.originalEvent` holds the source event.
51
+ */
30
52
  export declare class OhCard extends OhElement {
31
53
  static styles: import("lit").CSSResult[];
32
54
  variant: CardVariant;
33
55
  interactive: boolean;
34
56
  padding: CardPadding;
57
+ private _hasHeader;
58
+ private _hasFooter;
59
+ /** True when the slot holds an element or non-whitespace text */
60
+ private _slotHasContent;
61
+ private _onHeaderSlotChange;
62
+ private _onFooterSlotChange;
35
63
  private _handleClick;
36
64
  private _handleKeyDown;
37
65
  render(): import("lit").TemplateResult<1>;
@@ -1 +1 @@
1
- {"version":3,"file":"oh-card.d.ts","sourceRoot":"","sources":["../src/oh-card.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD,qBACa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,4BAwOpB;IAGF,OAAO,EAAE,WAAW,CAAY;IAGhC,WAAW,UAAS;IAGpB,OAAO,EAAE,WAAW,CAAQ;IAE5B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAOtB,MAAM;CA+BP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
1
+ {"version":3,"file":"oh-card.d.ts","sourceRoot":"","sources":["../src/oh-card.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,4BAyNpB;IAGF,OAAO,EAAE,WAAW,CAAa;IAGjC,WAAW,UAAS;IAGpB,OAAO,EAAE,WAAW,CAAQ;IAEnB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAEpC,iEAAiE;IACjE,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAOtB,MAAM;CA+BP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}