@taprootio/espalier 3.8.0 → 3.9.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.
@@ -1 +1 @@
1
- const T=.9,N=.88,_=.8;export{_ as BUTTON_ICON_INTERACTION_LIGHTNESS_FACTOR,T as BUTTON_ICON_SPLIT_LIGHTNESS_FACTOR,N as BUTTON_INTERACTION_LIGHTNESS_FACTOR};
1
+ const T=.88;export{T as BUTTON_INTERACTION_LIGHTNESS_FACTOR};
@@ -1,5 +1,6 @@
1
1
  import { type TemplateResult } from "lit";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
+ export type ButtonIconPosition = "left" | "right";
3
4
  /**
4
5
  * Used to initiate a user action or link to another page.
5
6
  *
@@ -29,6 +30,27 @@ import { EspalierElementBase } from "../shared/esp-element-base.js";
29
30
  * </div>
30
31
  * ```
31
32
  *
33
+ * Use `icon-position="left"` for a leading icon. The default `"right"`
34
+ * position keeps the icon trailing; both positions follow writing direction
35
+ * and therefore mirror in RTL.
36
+ *
37
+ * ```html
38
+ * <div style="display: flex; gap: var(--esp-size-padding);">
39
+ * <esp-button
40
+ * collapsed
41
+ * label="Save"
42
+ * icon="save"
43
+ * icon-position="left">
44
+ * </esp-button>
45
+ * <esp-button
46
+ * collapsed
47
+ * label="Next"
48
+ * icon="arrow-big-right"
49
+ * icon-position="right">
50
+ * </esp-button>
51
+ * </div>
52
+ * ```
53
+ *
32
54
  * @customElement esp-button
33
55
  * @slot - Optional custom SVG icon. Slotted icons override the
34
56
  * generated SVG from the `icon` attribute.
@@ -180,6 +202,18 @@ export declare class EspalierButton extends EspalierElementBase {
180
202
  * @type {string}
181
203
  */
182
204
  icon: string;
205
+ /**
206
+ * Places the optional icon on the logical leading (`"left"`) or trailing
207
+ * (`"right"`) side of the label. Logical placement mirrors in RTL.
208
+ *
209
+ * ```html
210
+ * <esp-button label="Save" icon="save" icon-position="left"></esp-button>
211
+ * <esp-button label="Next" icon="arrow-big-right" icon-position="right"></esp-button>
212
+ * ```
213
+ *
214
+ * @type {"left" | "right"}
215
+ */
216
+ iconPosition: ButtonIconPosition;
183
217
  /**
184
218
  * The label of the button.
185
219
  *
@@ -1,4 +1,4 @@
1
- var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,i):e,c;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(h,t,i,e);else for(var d=h.length-1;d>=0;d--)(c=h[d])&&(r=(a<3?c(r):a>3?c(t,i,r):c(t,i))||r);return a>3&&r&&Object.defineProperty(t,i,r),r};import{css as f,html as p,nothing as l}from"lit";import{customElement as m,eventOptions as v,property as s,state as y}from"lit/decorators.js";import{classMap as u}from"lit/directives/class-map.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ref as k}from"lit/directives/ref.js";import{getIconHrefForHost as x}from"../shared/intent-values.js";import{SlottedIconController as T}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as w}from"../shared/svgs/render-sprite-icon.js";import{BUTTON_ICON_INTERACTION_LIGHTNESS_FACTOR as S,BUTTON_ICON_SPLIT_LIGHTNESS_FACTOR as g,BUTTON_INTERACTION_LIGHTNESS_FACTOR as $}from"./action-state-lightness.js";const N=p`<svg
1
+ var n=function(h,t,r,o){var a=arguments.length,i=a<3?t:o===null?o=Object.getOwnPropertyDescriptor(t,r):o,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(h,t,r,o);else for(var c=h.length-1;c>=0;c--)(d=h[c])&&(i=(a<3?d(i):a>3?d(t,r,i):d(t,r))||i);return a>3&&i&&Object.defineProperty(t,r,i),i};import{css as f,html as p,nothing as l}from"lit";import{customElement as g,eventOptions as m,property as s,state as v}from"lit/decorators.js";import{classMap as u}from"lit/directives/class-map.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ref as y}from"lit/directives/ref.js";import{getIconHrefForHost as w}from"../shared/intent-values.js";import{SlottedIconController as x}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as k}from"../shared/svgs/render-sprite-icon.js";import{BUTTON_INTERACTION_LIGHTNESS_FACTOR as T}from"./action-state-lightness.js";const S=p`<svg
2
2
  xmlns="http://www.w3.org/2000/svg"
3
3
  viewBox="0 0 24 24"
4
4
  fill="none"
@@ -10,40 +10,40 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
10
10
  >
11
11
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
12
12
  <path d="M4.05 11a8 8 0 1 1 .5 4m-.5 5v-5h5" />
13
- </svg>`;let o=class extends b{constructor(){super(...arguments),this.iconSlot=new T(this),this.innerTabindex=null,this.neutralizingTabindex=!1,this.buttonType="button",this.collapsed=!1,this.disabled=!1,this.href="",this.iconOnly=!1,this.incognito=!1,this.icon="",this.label="",this.loading=!1,this.target="",this.rel="",this.formNoValidate=!1,this.buildIcon=t=>this.loading?p` <span>${N}</span> `:p`
13
+ </svg>`;let e=class extends b{constructor(){super(...arguments),this.iconSlot=new x(this),this.innerTabindex=null,this.neutralizingTabindex=!1,this.buttonType="button",this.collapsed=!1,this.disabled=!1,this.href="",this.iconOnly=!1,this.incognito=!1,this.icon="",this.iconPosition="right",this.label="",this.loading=!1,this.target="",this.rel="",this.formNoValidate=!1,this.buildIcon=t=>this.loading?p` <span>${S}</span> `:p`
14
14
  <span>
15
- <slot ${k(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
16
- ${!this.iconSlot.hasSlottedIcon(":scope > *")&&t?w(t):l}
15
+ <slot ${y(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
16
+ ${!this.iconSlot.hasSlottedIcon(":scope > *")&&t?k(t):l}
17
17
  </span>
18
- `}static get observedAttributes(){return[...super.observedAttributes,"tabindex","aria-pressed"]}attributeChangedCallback(t,i,e){if(super.attributeChangedCallback(t,i,e),t==="aria-pressed"){this.requestUpdate();return}if(t!=="tabindex"||this.neutralizingTabindex)return;const a=e===null?null:Number(e),r=a===null||Number.isNaN(a)?null:a;r!==null&&r>=0?(this.innerTabindex=r,this.writeHostTabindex(null)):r===null&&e!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=r}writeHostTabindex(t){this.getAttribute("tabindex")!==t&&(this.neutralizingTabindex=!0,t===null?this.removeAttribute("tabindex"):this.setAttribute("tabindex",t),this.neutralizingTabindex=!1)}removeAttribute(t){super.removeAttribute(t),t==="tabindex"&&!this.neutralizingTabindex&&(this.innerTabindex=null)}focus(t){this.focusShadowElementAfterUpdate("button, a",t)}handleClick(t){if(this.dispatchEvent(new CustomEvent("clicked",{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const i=this.closest("form");if(i){const e=document.createElement("button");e.type="submit",e.hidden=!0,this.formNoValidate&&(e.formNoValidate=!0),i.appendChild(e),i.requestSubmit(e),e.remove()}}else this.buttonType==="reset"&&this.closest("form")?.reset()}render(){const t=x(this.icon,this),i=this.loading||this.iconSlot.hasSlottedIcon(":scope > *")||t.length>0,{collapsed:e,iconOnly:a}=this,r=a?this.getAttribute("aria-label")||this.label||l:l,c=this.getAttribute("aria-pressed")||l,d={"esp-field":!0,"icon-only":a,incognito:this.incognito,"is-collapsed":e,"has-icon":i};return this.href.length?p`
19
- <div part="wrapper" class=${u(d)}>
18
+ `}static get observedAttributes(){return[...super.observedAttributes,"tabindex","aria-pressed"]}attributeChangedCallback(t,r,o){if(super.attributeChangedCallback(t,r,o),t==="aria-pressed"){this.requestUpdate();return}if(t!=="tabindex"||this.neutralizingTabindex)return;const a=o===null?null:Number(o),i=a===null||Number.isNaN(a)?null:a;i!==null&&i>=0?(this.innerTabindex=i,this.writeHostTabindex(null)):i===null&&o!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=i}writeHostTabindex(t){this.getAttribute("tabindex")!==t&&(this.neutralizingTabindex=!0,t===null?this.removeAttribute("tabindex"):this.setAttribute("tabindex",t),this.neutralizingTabindex=!1)}removeAttribute(t){super.removeAttribute(t),t==="tabindex"&&!this.neutralizingTabindex&&(this.innerTabindex=null)}focus(t){this.focusShadowElementAfterUpdate("button, a",t)}handleClick(t){if(this.dispatchEvent(new CustomEvent("clicked",{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const r=this.closest("form");if(r){const o=document.createElement("button");o.type="submit",o.hidden=!0,this.formNoValidate&&(o.formNoValidate=!0),r.appendChild(o),r.requestSubmit(o),o.remove()}}else this.buttonType==="reset"&&this.closest("form")?.reset()}render(){const t=w(this.icon,this),r=this.loading||this.iconSlot.hasSlottedIcon(":scope > *")||t.length>0,{collapsed:o,iconOnly:a}=this,i=a?this.getAttribute("aria-label")||this.label||l:l,d=this.getAttribute("aria-pressed")||l,c={"esp-field":!0,"icon-only":a,incognito:this.incognito,"is-collapsed":o,"has-icon":r,"icon-left":r&&!a&&this.iconPosition==="left"};return this.href.length?p`
19
+ <div part="wrapper" class=${u(c)}>
20
20
  <a
21
21
  ?disabled=${this.disabled}
22
22
  href=${this.href}
23
23
  target=${this.target}
24
24
  rel=${this.rel||l}
25
25
  tabindex=${this.innerTabindex??l}
26
- aria-label=${r}
26
+ aria-label=${i}
27
27
  >
28
28
  <span>${this.label??""}</span>
29
29
  ${this.buildIcon(t)}
30
30
  </a>
31
31
  </div>
32
32
  `:p`
33
- <div part="wrapper" class=${u(d)}>
33
+ <div part="wrapper" class=${u(c)}>
34
34
  <button
35
35
  ?disabled=${this.disabled||this.loading}
36
36
  @click=${this.handleClick}
37
37
  type=${this.buttonType}
38
38
  tabindex=${this.innerTabindex??l}
39
- aria-label=${r}
40
- aria-pressed=${c}
39
+ aria-label=${i}
40
+ aria-pressed=${d}
41
41
  >
42
42
  <span>${this.label??""}</span>
43
43
  ${this.buildIcon(t)}
44
44
  </button>
45
45
  </div>
46
- `}};o.styles=[...b.styles,f`
46
+ `}};e.styles=[...b.styles,f`
47
47
  :host {
48
48
  --_esp-button-radius: var(--esp-size-border-radius);
49
49
  }
@@ -81,15 +81,8 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
81
81
  }
82
82
 
83
83
  > span:nth-child(2) {
84
- background-color: oklch(
85
- from var(--esp-color-action-background)
86
- calc(l * ${g}) c h
87
- );
88
84
  display: none;
89
85
  place-content: center;
90
- border-left: 1px dotted var(--esp-color-border);
91
- border-bottom-right-radius: max(0px, calc(var(--_esp-button-radius) - 0.1rem));
92
- border-top-right-radius: max(0px, calc(var(--_esp-button-radius) - 0.1rem));
93
86
  padding: var(--esp-button-padding, var(--esp-size-padding));
94
87
 
95
88
  .generated-icon,
@@ -101,6 +94,17 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
101
94
  }
102
95
  }
103
96
 
97
+ &.icon-left {
98
+ button,
99
+ a {
100
+ grid-template-columns: min-content auto;
101
+
102
+ > span:nth-child(2) {
103
+ order: -1;
104
+ }
105
+ }
106
+ }
107
+
104
108
  &.has-icon {
105
109
  button,
106
110
  a {
@@ -123,7 +127,6 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
123
127
  }
124
128
 
125
129
  > span:nth-child(2) {
126
- background-color: var(--esp-color-action-background);
127
130
  border: none;
128
131
  border-radius: var(--_esp-button-radius);
129
132
  }
@@ -136,24 +139,12 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
136
139
  &:hover,
137
140
  &:focus-within {
138
141
  background-color: oklch(
139
- from var(--esp-color-action-background) calc(l * ${$})
142
+ from var(--esp-color-action-background) calc(l * ${T})
140
143
  c h
141
144
  );
142
-
143
- button,
144
- a {
145
- > span:nth-child(2) {
146
- background-color: oklch(
147
- from var(--esp-color-action-background)
148
- calc(l * ${S}) c h
149
- );
150
- border-color: oklch(from var(--esp-color-border) calc(l * 1.2) c h);
151
- }
152
- }
153
145
  }
154
146
 
155
147
  &.incognito {
156
- grid-template-columns: min-content auto;
157
148
  background-color: transparent;
158
149
  border-color: transparent;
159
150
  color: var(--esp-color-text);
@@ -162,17 +153,27 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
162
153
  button,
163
154
  a {
164
155
  > span:nth-child(1) {
165
- grid-column: 2;
166
- justify-content: left;
156
+ justify-content: start;
167
157
  padding: var(--esp-button-incognito-padding, var(--esp-size-tiny)) 0;
168
- padding-right: calc(2 * var(--esp-button-incognito-padding, var(--esp-size-tiny)));
158
+ padding-inline-end: calc(
159
+ 2 * var(--esp-button-incognito-padding, var(--esp-size-tiny))
160
+ );
169
161
  }
170
162
 
171
163
  > span:nth-child(2) {
172
- grid-row: 1;
173
- grid-column: 1;
174
164
  background-color: transparent;
175
- border-color: transparent;
165
+ }
166
+ }
167
+
168
+ &.icon-left {
169
+ button,
170
+ a {
171
+ > span:nth-child(1) {
172
+ padding-inline-start: calc(
173
+ 2 * var(--esp-button-incognito-padding, var(--esp-size-tiny))
174
+ );
175
+ padding-inline-end: 0;
176
+ }
176
177
  }
177
178
  }
178
179
 
@@ -193,17 +194,6 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
193
194
  &:has(button:disabled):hover,
194
195
  &:has(button:disabled):focus-within {
195
196
  background-color: var(--esp-color-action-background);
196
-
197
- button,
198
- a {
199
- > span:nth-child(2) {
200
- background-color: oklch(
201
- from var(--esp-color-action-background)
202
- calc(l * ${g}) c h
203
- );
204
- border-color: var(--esp-color-border);
205
- }
206
- }
207
197
  }
208
198
 
209
199
  svg.rotate {
@@ -223,4 +213,4 @@ var n=function(h,t,i,e){var a=arguments.length,r=a<3?t:e===null?e=Object.getOwnP
223
213
  transform: rotate(360deg);
224
214
  }
225
215
  }
226
- `],n([y()],o.prototype,"innerTabindex",void 0),n([s({attribute:"button-type",type:String})],o.prototype,"buttonType",void 0),n([s({type:Boolean})],o.prototype,"collapsed",void 0),n([s({type:Boolean,reflect:!0})],o.prototype,"disabled",void 0),n([s({type:String})],o.prototype,"href",void 0),n([s({attribute:"icon-only",type:Boolean})],o.prototype,"iconOnly",void 0),n([s({type:Boolean,reflect:!0})],o.prototype,"incognito",void 0),n([s({type:String})],o.prototype,"icon",void 0),n([s({type:String})],o.prototype,"label",void 0),n([s({type:Boolean,reflect:!0})],o.prototype,"loading",void 0),n([s({type:String})],o.prototype,"target",void 0),n([s({type:String})],o.prototype,"rel",void 0),n([s({attribute:"formnovalidate",type:Boolean})],o.prototype,"formNoValidate",void 0),n([v({capture:!1,passive:!0})],o.prototype,"handleClick",null),o=n([m("esp-button")],o);export{o as EspalierButton};
216
+ `],n([v()],e.prototype,"innerTabindex",void 0),n([s({attribute:"button-type",type:String})],e.prototype,"buttonType",void 0),n([s({type:Boolean})],e.prototype,"collapsed",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"disabled",void 0),n([s({type:String})],e.prototype,"href",void 0),n([s({attribute:"icon-only",type:Boolean})],e.prototype,"iconOnly",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"incognito",void 0),n([s({type:String})],e.prototype,"icon",void 0),n([s({attribute:"icon-position",type:String})],e.prototype,"iconPosition",void 0),n([s({type:String})],e.prototype,"label",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"loading",void 0),n([s({type:String})],e.prototype,"target",void 0),n([s({type:String})],e.prototype,"rel",void 0),n([s({attribute:"formnovalidate",type:Boolean})],e.prototype,"formNoValidate",void 0),n([m({capture:!1,passive:!0})],e.prototype,"handleClick",null),e=n([g("esp-button")],e);export{e as EspalierButton};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",