vira 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,11 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.allElementBookEntries = void 0;
4
4
  const elements_book_1 = require("../elements/elements.book");
5
5
  const vira_button_element_book_1 = require("../elements/vira-button/vira-button.element.book");
6
+ const vira_collapsible_wrapper_element_book_1 = require("../elements/vira-collapsible/vira-collapsible-wrapper.element.book");
6
7
  const vira_icon_element_book_1 = require("../elements/vira-icon/vira-icon.element.book");
8
+ const vira_input_element_book_1 = require("../elements/vira-input/vira-input.element.book");
7
9
  const icons_book_1 = require("../icons/icons.book");
8
10
  exports.allElementBookEntries = [
9
11
  elements_book_1.elementsBookChapter,
10
12
  ...icons_book_1.iconBookEntries,
11
13
  ...vira_button_element_book_1.viraButtonBookEntries,
14
+ ...vira_collapsible_wrapper_element_book_1.viraCollapsibleBookEntries,
12
15
  ...vira_icon_element_book_1.viraIconBookEntries,
16
+ ...vira_input_element_book_1.viraInputBookEntries,
13
17
  ];
@@ -1,4 +1,6 @@
1
1
  /** This file is automatically updated by update-element-exports.ts */
2
2
  export * from './define-vira-element';
3
3
  export * from './vira-button/vira-button.element';
4
+ export * from './vira-collapsible/vira-collapsible-wrapper.element';
4
5
  export * from './vira-icon/vira-icon.element';
6
+ export * from './vira-input/vira-input.element';
@@ -17,4 +17,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  __exportStar(require("./define-vira-element"), exports);
19
19
  __exportStar(require("./vira-button/vira-button.element"), exports);
20
+ __exportStar(require("./vira-collapsible/vira-collapsible-wrapper.element"), exports);
20
21
  __exportStar(require("./vira-icon/vira-icon.element"), exports);
22
+ __exportStar(require("./vira-input/vira-input.element"), exports);
@@ -5,7 +5,7 @@ export declare enum ViraButtonStyleEnum {
5
5
  }
6
6
  export declare const ViraButton: import("element-vir").DeclarativeElementDefinition<"vira-button", {
7
7
  text?: string;
8
- icon?: undefined | ViraIconSvg;
8
+ icon?: undefined | Pick<ViraIconSvg, 'svgTemplate'>;
9
9
  disabled?: boolean | undefined;
10
10
  buttonStyle?: ViraButtonStyleEnum | undefined;
11
- }, {}, {}, "vira-button-outline-style" | "vira-button-disabled", "vira-button-primary-color" | "vira-button-primary-hover-color" | "vira-button-primary-active-color" | "vira-button-secondary-color" | "vira-button-internal-foreground-color" | "vira-button-internal-background-color", import("lit-html").HTMLTemplateResult>;
11
+ }, {}, {}, "vira-button-outline-style" | "vira-button-disabled", "vira-button-primary-color" | "vira-button-primary-hover-color" | "vira-button-primary-active-color" | "vira-button-secondary-color" | "vira-button-internal-foreground-color" | "vira-button-internal-background-color" | "vira-button-padding", import("lit-html").HTMLTemplateResult>;
@@ -7,6 +7,7 @@ const disabled_1 = require("../../styles/disabled");
7
7
  const durations_1 = require("../../styles/durations");
8
8
  const focus_1 = require("../../styles/focus");
9
9
  const native_styles_1 = require("../../styles/native-styles");
10
+ const vira_css_vars_1 = require("../../styles/vira-css-vars");
10
11
  const define_vira_element_1 = require("../define-vira-element");
11
12
  const vira_icon_element_1 = require("../vira-icon/vira-icon.element");
12
13
  var ViraButtonStyleEnum;
@@ -29,6 +30,7 @@ exports.ViraButton = (0, define_vira_element_1.defineViraElement)()({
29
30
  'vira-button-secondary-color': 'white',
30
31
  'vira-button-internal-foreground-color': '',
31
32
  'vira-button-internal-background-color': '',
33
+ 'vira-button-padding': '5px 10px',
32
34
  },
33
35
  styles: ({ hostClasses, cssVars }) => (0, element_vir_1.css) `
34
36
  :host {
@@ -65,6 +67,7 @@ exports.ViraButton = (0, define_vira_element_1.defineViraElement)()({
65
67
  }
66
68
 
67
69
  button {
70
+ cursor: pointer;
68
71
  ${native_styles_1.removeNativeFormStyles};
69
72
  position: relative;
70
73
  width: 100%;
@@ -75,10 +78,10 @@ exports.ViraButton = (0, define_vira_element_1.defineViraElement)()({
75
78
  display: inline-flex;
76
79
  justify-content: center;
77
80
  align-items: center;
78
- border-radius: 8px;
81
+ border-radius: ${vira_css_vars_1.viraCssVars['vira-form-input-border-radius'].value};
79
82
  background-color: ${cssVars['vira-button-internal-background-color'].value};
80
83
  color: ${cssVars['vira-button-internal-foreground-color'].value};
81
- padding: 5px 10px;
84
+ padding: ${cssVars['vira-button-padding'].value};
82
85
  transition: color ${durations_1.viraAnimationDurations['vira-interaction-animation-duration'].value},
83
86
  background-color
84
87
  ${durations_1.viraAnimationDurations['vira-interaction-animation-duration'].value},
@@ -86,7 +89,7 @@ exports.ViraButton = (0, define_vira_element_1.defineViraElement)()({
86
89
  }
87
90
 
88
91
  ${(0, focus_1.createFocusStyles)({
89
- mainSelector: 'button:focus:focus-visible:not(:active)',
92
+ mainSelector: 'button:focus:focus-visible:not(:active):not([disabled])',
90
93
  elementBorderSize: 2,
91
94
  })}
92
95
 
@@ -110,7 +113,7 @@ exports.ViraButton = (0, define_vira_element_1.defineViraElement)()({
110
113
  `
111
114
  : '';
112
115
  return (0, element_vir_1.html) `
113
- <button>${iconTemplate} ${textTemplate}</button>
116
+ <button ?disabled=${inputs.disabled}>${iconTemplate} ${textTemplate}</button>
114
117
  `;
115
118
  },
116
119
  });
@@ -0,0 +1,10 @@
1
+ export declare enum ViraCollapsibleSlotNameEnum {
2
+ Header = "header"
3
+ }
4
+ export declare const ViraCollapsibleWrapper: import("element-vir").DeclarativeElementDefinition<"vira-collapsible-wrapper", {
5
+ expanded: boolean;
6
+ }, {
7
+ contentHeight: number;
8
+ }, {
9
+ expandChange: import("element-vir").DefinedTypedEventNameDefinition<boolean>;
10
+ }, "vira-collapsible-wrapper-expanded", `vira-collapsible-wrapper-${string}`, import("lit-html").HTMLTemplateResult>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViraCollapsibleWrapper = exports.ViraCollapsibleSlotNameEnum = void 0;
4
+ const element_vir_1 = require("element-vir");
5
+ const styles_1 = require("../../styles");
6
+ const define_vira_element_1 = require("../define-vira-element");
7
+ var ViraCollapsibleSlotNameEnum;
8
+ (function (ViraCollapsibleSlotNameEnum) {
9
+ ViraCollapsibleSlotNameEnum["Header"] = "header";
10
+ })(ViraCollapsibleSlotNameEnum = exports.ViraCollapsibleSlotNameEnum || (exports.ViraCollapsibleSlotNameEnum = {}));
11
+ exports.ViraCollapsibleWrapper = (0, define_vira_element_1.defineViraElement)()({
12
+ tagName: 'vira-collapsible-wrapper',
13
+ hostClasses: {
14
+ 'vira-collapsible-wrapper-expanded': ({ inputs }) => inputs.expanded,
15
+ },
16
+ styles: ({ hostClasses }) => (0, element_vir_1.css) `
17
+ :host {
18
+ display: flex;
19
+ flex-direction: column;
20
+ }
21
+
22
+ .header-wrapper {
23
+ ${styles_1.removeNativeFormStyles};
24
+ cursor: pointer;
25
+ }
26
+
27
+ .content-wrapper,
28
+ .collapsing-element {
29
+ display: flex;
30
+ flex-direction: column;
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ .collapsing-element {
35
+ transition: height ${styles_1.viraAnimationDurations['vira-pretty-animation-duration'].value};
36
+ overflow: hidden;
37
+ }
38
+ ${hostClasses['vira-collapsible-wrapper-expanded'].name} .collapsing-element {
39
+ pointer-events: none;
40
+ }
41
+ `,
42
+ events: {
43
+ expandChange: (0, element_vir_1.defineElementEvent)(),
44
+ },
45
+ stateInitStatic: {
46
+ contentHeight: 0,
47
+ },
48
+ renderCallback({ state, updateState, dispatch, events, inputs }) {
49
+ const collapsingStyles = inputs.expanded
50
+ ? (0, element_vir_1.css) `
51
+ height: ${state.contentHeight}px;
52
+ `
53
+ : (0, element_vir_1.css) `
54
+ height: 0;
55
+ `;
56
+ return (0, element_vir_1.html) `
57
+ <button
58
+ class="header-wrapper"
59
+ ${(0, element_vir_1.listen)('click', () => {
60
+ dispatch(new events.expandChange(!inputs.expanded));
61
+ })}
62
+ >
63
+ <slot name=${ViraCollapsibleSlotNameEnum.Header}>Header</slot>
64
+ </button>
65
+ <div class="collapsing-element" style=${collapsingStyles} disabled="disabled">
66
+ <div
67
+ ${(0, element_vir_1.onResize)(({ contentRect }) => {
68
+ updateState({ contentHeight: contentRect.height });
69
+ })}
70
+ class="content-wrapper"
71
+ >
72
+ <slot></slot>
73
+ </div>
74
+ </div>
75
+ `;
76
+ },
77
+ });
@@ -1,6 +1,6 @@
1
1
  import { ViraIconSvg } from '../../icons/icon-svg';
2
2
  export declare const ViraIcon: import("element-vir").DeclarativeElementDefinition<"vira-icon", {
3
- icon: ViraIconSvg | undefined;
3
+ icon: Pick<ViraIconSvg, 'svgTemplate'> | undefined;
4
4
  /** Ignores the given icon's embedded size and causes the <svg> element to fill its parent. */
5
5
  fitContainer?: boolean | undefined;
6
6
  }, {}, {}, "vira-icon-fit-container", `vira-icon-${string}`, import("lit-html").TemplateResult | "">;
@@ -0,0 +1,39 @@
1
+ import { ViraIconSvg } from '../../icons';
2
+ export declare const ViraInput: import("element-vir").DeclarativeElementDefinition<"vira-input", {
3
+ icon?: undefined | Pick<ViraIconSvg, 'svgTemplate'>;
4
+ value: string;
5
+ /** Shown when no other text is present. Input restrictions do not apply to this property. */
6
+ placeholder?: string;
7
+ /** Set to true to trigger disabled styles and to block all user input. */
8
+ disabled?: boolean;
9
+ /**
10
+ * Only letters in the given string or matches to the given RegExp will be allowed.
11
+ * blockedInputs takes precedence over this input.
12
+ *
13
+ * For example: if allowedInputs is set to "abcd" and blockedInputs is set to "d", only "a",
14
+ * "b", or "c" letters will be allowed.
15
+ */
16
+ allowedInputs?: string | RegExp;
17
+ /** Any letters in the given string or matches to the given RegExp will be blocked. */
18
+ blockedInputs?: string | RegExp;
19
+ /** Disable all browser helps like spellchecking, autocomplete, etc. */
20
+ disableBrowserHelps?: boolean;
21
+ /** A suffix that, if provided, is shown following the user input field. */
22
+ suffix?: string;
23
+ /** Set this to true to make the whole element size to only fit the input text. */
24
+ fitText?: boolean;
25
+ }, {
26
+ forcedInputWidth: number;
27
+ }, {
28
+ /**
29
+ * Fires whenever a user input created a new value. Does not fire if all input letters are
30
+ * filtered out due to input restrictions.
31
+ */
32
+ valueChange: import("element-vir").DefinedTypedEventNameDefinition<string>;
33
+ /**
34
+ * Fires when inputs are blocked. Useful for showing warnings or error messages to inform
35
+ * the user why their input did not propagate if it was blocked. This does not fire for text
36
+ * that was blocked out of programmatic "value" property assignments.
37
+ */
38
+ inputBlocked: import("element-vir").DefinedTypedEventNameDefinition<string>;
39
+ }, "vira-input-disabled" | "vira-input-has-value" | "vira-input-fit-text", "vira-input-placeholder-color" | "vira-input-text-color" | "vira-input-border-color" | "vira-input-focus-border-color" | "vira-input-text-selection-color" | "vira-input-padding-horizontal" | "vira-input-padding-vertical", import("lit-html").HTMLTemplateResult>;
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViraInput = void 0;
4
+ const element_vir_1 = require("element-vir");
5
+ const styles_1 = require("../../styles");
6
+ const focus_1 = require("../../styles/focus");
7
+ const native_styles_1 = require("../../styles/native-styles");
8
+ const vira_css_vars_1 = require("../../styles/vira-css-vars");
9
+ const define_vira_element_1 = require("../define-vira-element");
10
+ const vira_icon_element_1 = require("../vira-icon/vira-icon.element");
11
+ function doesMatch({ input, matcher }) {
12
+ if (!input || !matcher) {
13
+ return true;
14
+ }
15
+ if (input.length > 1) {
16
+ return !!input.split('').every((singleInput) => doesMatch({ input: singleInput, matcher }));
17
+ }
18
+ if (matcher instanceof RegExp) {
19
+ return !!input.match(matcher);
20
+ }
21
+ else {
22
+ return matcher.includes(input);
23
+ }
24
+ }
25
+ function isAllowed({ value, allowed, blocked }) {
26
+ const isAllowedCharacter = allowed
27
+ ? doesMatch({
28
+ input: value,
29
+ matcher: allowed,
30
+ })
31
+ : true;
32
+ const isBlockedCharacter = blocked
33
+ ? doesMatch({
34
+ input: value,
35
+ matcher: blocked,
36
+ })
37
+ : false;
38
+ return isAllowedCharacter && !isBlockedCharacter;
39
+ }
40
+ function filterToAllowedCharactersOnly(inputs) {
41
+ if (!inputs.value) {
42
+ return { filtered: inputs.value, blocked: '' };
43
+ }
44
+ const { filtered, blocked } = inputs.value.split('').reduce((accum, letter) => {
45
+ const allowed = isAllowed({ ...inputs, value: letter });
46
+ if (allowed) {
47
+ accum.filtered.push(letter);
48
+ }
49
+ else {
50
+ accum.blocked.push(letter);
51
+ }
52
+ return accum;
53
+ }, {
54
+ filtered: [],
55
+ blocked: [],
56
+ });
57
+ return {
58
+ filtered: filtered.join(''),
59
+ blocked: blocked.join(''),
60
+ };
61
+ }
62
+ exports.ViraInput = (0, define_vira_element_1.defineViraElement)()({
63
+ tagName: 'vira-input',
64
+ hostClasses: {
65
+ 'vira-input-disabled': ({ inputs }) => !!inputs.disabled,
66
+ 'vira-input-has-value': ({ inputs }) => !!inputs.value,
67
+ 'vira-input-fit-text': ({ inputs }) => !!inputs.fitText,
68
+ },
69
+ cssVars: {
70
+ 'vira-input-placeholder-color': '#ccc',
71
+ 'vira-input-text-color': 'black',
72
+ 'vira-input-border-color': '#ccc',
73
+ 'vira-input-focus-border-color': '#59B1FF',
74
+ 'vira-input-text-selection-color': '#CFE9FF',
75
+ 'vira-input-padding-horizontal': '10px',
76
+ 'vira-input-padding-vertical': '6px',
77
+ },
78
+ events: {
79
+ /**
80
+ * Fires whenever a user input created a new value. Does not fire if all input letters are
81
+ * filtered out due to input restrictions.
82
+ */
83
+ valueChange: (0, element_vir_1.defineElementEvent)(),
84
+ /**
85
+ * Fires when inputs are blocked. Useful for showing warnings or error messages to inform
86
+ * the user why their input did not propagate if it was blocked. This does not fire for text
87
+ * that was blocked out of programmatic "value" property assignments.
88
+ */
89
+ inputBlocked: (0, element_vir_1.defineElementEvent)(),
90
+ },
91
+ styles: ({ hostClasses, cssVars }) => {
92
+ return (0, element_vir_1.css) `
93
+ :host {
94
+ position: relative;
95
+ display: inline-flex;
96
+ width: 224px;
97
+ box-sizing: border-box;
98
+ ${focus_1.viraFocusCssVars['vira-focus-outline-color'].name}: ${cssVars['vira-input-focus-border-color'].value};
99
+ color: ${cssVars['vira-input-text-color'].value};
100
+ }
101
+
102
+ ${hostClasses['vira-input-disabled'].selector} {
103
+ ${styles_1.viraDisabledStyles};
104
+ }
105
+
106
+ ${hostClasses['vira-input-fit-text'].selector} {
107
+ width: unset;
108
+ }
109
+ ${hostClasses['vira-input-fit-text'].selector} input {
110
+ flex-grow: 0;
111
+ }
112
+ ${hostClasses['vira-input-fit-text'].selector} input.has-value {
113
+ /*
114
+ Account for weird Safari <input> behavior with text alignment and size. so we
115
+ don't lose a pixel on the left side.
116
+ Only apply this when <input> has a value, otherwise externally-set width and a
117
+ placeholder input will cause the text selector bar to initially be in the center
118
+ of the element.
119
+ */
120
+ text-align: center;
121
+ }
122
+ ${hostClasses['vira-input-fit-text'].selector} .size-span {
123
+ ${native_styles_1.removeNativeFormStyles};
124
+ font-family: inherit;
125
+ display: inline-block;
126
+ font-size: inherit;
127
+ line-height: inherit;
128
+ box-sizing: border-box;
129
+ position: absolute;
130
+ opacity: 0;
131
+ visibility: hidden;
132
+ pointer-events: none;
133
+ z-index: -1;
134
+ width: min-content;
135
+ ${styles_1.noUserSelect};
136
+ vertical-align: middle;
137
+ max-height: 100%;
138
+ }
139
+
140
+ pre {
141
+ ${native_styles_1.removeNativeFormStyles};
142
+ font: inherit;
143
+ /*
144
+ Leave at least a few pixels for the cursor bar when there is no text at all.
145
+ This also accounts for a weird Safari <input> behavior where the text moves
146
+ around if it's not given a tiny bit of padding.
147
+ */
148
+ padding-left: 2px;
149
+ display: block;
150
+ }
151
+
152
+ .border-style {
153
+ position: absolute;
154
+ top: 0;
155
+ left: 0;
156
+ width: 100%;
157
+ height: 100%;
158
+ border-radius: ${vira_css_vars_1.viraCssVars['vira-form-input-border-radius'].value};
159
+ z-index: 0;
160
+ pointer-events: none;
161
+ }
162
+
163
+ .label-border {
164
+ top: -1px;
165
+ left: -1px;
166
+ border: 1px solid ${cssVars['vira-input-border-color'].value};
167
+ transition: border
168
+ ${styles_1.viraAnimationDurations['vira-interaction-animation-duration'].value};
169
+ }
170
+
171
+ label {
172
+ ${native_styles_1.removeNativeFormStyles};
173
+ max-width: 100%;
174
+ flex-grow: 1;
175
+ cursor: pointer;
176
+ display: inline-flex;
177
+ box-sizing: border-box;
178
+ align-items: center;
179
+ position: relative;
180
+ padding: 0 ${cssVars['vira-input-padding-horizontal'].value};
181
+ border-radius: ${vira_css_vars_1.viraCssVars['vira-form-input-border-radius'].value};
182
+ background-color: transparent;
183
+ /*
184
+ Border colors are actually applied via the .label-border class. However, we must
185
+ apply a border here still so that it takes up space.
186
+ */
187
+ border: 1px solid transparent;
188
+ gap: 4px;
189
+ }
190
+
191
+ ${(0, focus_1.createFocusStyles)({
192
+ mainSelector: 'input:focus:focus-visible:not(:active):not([disabled]) ~ .focus-border',
193
+ elementBorderSize: 0,
194
+ })}
195
+
196
+ ${vira_icon_element_1.ViraIcon} {
197
+ margin-right: calc(${cssVars['vira-input-padding-horizontal'].value} - 4px);
198
+ }
199
+
200
+ input {
201
+ ${native_styles_1.removeNativeFormStyles};
202
+ cursor: text;
203
+ margin: ${cssVars['vira-input-padding-vertical'].value} 0;
204
+ flex-grow: 1;
205
+ max-width: 100%;
206
+ /* fix input element not shrinking by default */
207
+ width: 0;
208
+ text-overflow: ellipsis;
209
+ box-sizing: border-box;
210
+ overflow: hidden;
211
+ }
212
+
213
+ ::selection {
214
+ background: ${cssVars['vira-input-text-selection-color']
215
+ .value}; /* WebKit/Blink Browsers */
216
+ }
217
+ ::-moz-selection {
218
+ background: ${cssVars['vira-input-text-selection-color']
219
+ .value}; /* Gecko Browsers */
220
+ }
221
+
222
+ input:placeholder-shown {
223
+ text-overflow: ellipsis;
224
+ overflow: hidden;
225
+ }
226
+
227
+ input:focus {
228
+ outline: none;
229
+ }
230
+
231
+ input::placeholder {
232
+ color: ${cssVars['vira-input-placeholder-color'].value};
233
+ }
234
+
235
+ .suffix {
236
+ font-weight: bold;
237
+ }
238
+ `;
239
+ },
240
+ stateInitStatic: {
241
+ forcedInputWidth: 0,
242
+ },
243
+ renderCallback: ({ inputs, dispatch, state, updateState, events }) => {
244
+ const { filtered: filteredValue } = filterToAllowedCharactersOnly({
245
+ value: inputs.value ?? '',
246
+ allowed: inputs.allowedInputs,
247
+ blocked: inputs.blockedInputs,
248
+ });
249
+ const iconTemplate = inputs.icon
250
+ ? (0, element_vir_1.html) `
251
+ <${vira_icon_element_1.ViraIcon} ${(0, element_vir_1.assign)(vira_icon_element_1.ViraIcon, { icon: inputs.icon })}></${vira_icon_element_1.ViraIcon}>
252
+ `
253
+ : '';
254
+ const forcedInputWidthStyles = inputs.fitText
255
+ ? (0, element_vir_1.css) `
256
+ width: ${state.forcedInputWidth}px;
257
+ `
258
+ : '';
259
+ return (0, element_vir_1.html) `
260
+ <label>
261
+ ${iconTemplate}
262
+ ${(0, element_vir_1.renderIf)(!!inputs.fitText, (0, element_vir_1.html) `
263
+ <span
264
+ class="size-span"
265
+ ${(0, element_vir_1.onResize)(({ contentRect }) => {
266
+ updateState({ forcedInputWidth: contentRect.width });
267
+ })}
268
+ >
269
+ <pre>${filteredValue || inputs.placeholder || ''}</pre>
270
+ </span>
271
+ `)}
272
+ <input
273
+ class=${(0, element_vir_1.classMap)({
274
+ 'have-value': !!filteredValue,
275
+ })}
276
+ style=${forcedInputWidthStyles}
277
+ autocomplete=${inputs.disableBrowserHelps ? 'off' : ''}
278
+ autocorrect=${inputs.disableBrowserHelps ? 'off' : ''}
279
+ autocapitalize=${inputs.disableBrowserHelps ? 'off' : ''}
280
+ spellcheck=${inputs.disableBrowserHelps ? 'false' : ''}
281
+ ?disabled=${inputs.disabled}
282
+ .value=${filteredValue}
283
+ ${(0, element_vir_1.listen)('input', (event) => {
284
+ /**
285
+ * When attached to an input element (like here) this event type should
286
+ * always be InputEvent.
287
+ */
288
+ if (!(event instanceof InputEvent)) {
289
+ throw new Error(`Input event type mismatch: "${event.constructor.name}"`);
290
+ }
291
+ const inputElement = event.target;
292
+ if (!(inputElement instanceof HTMLInputElement)) {
293
+ throw new Error(`Failed to find input element target from input event.`);
294
+ }
295
+ /**
296
+ * This is usually a single character, but can be a bunch of characters in
297
+ * some circumstances. For example, when a bunch of characters are pasted,
298
+ * this will be the entire pasted contents.
299
+ */
300
+ const changedText = event.data;
301
+ const beforeChangeText = filteredValue;
302
+ // this will be overwritten below if blocked characters are encountered
303
+ let finalText = inputElement.value ?? '';
304
+ /**
305
+ * When changedText is falsy, that means an operation other than inserting
306
+ * characters happened. Such as: deleting, cutting the text, etc.
307
+ */
308
+ if (changedText) {
309
+ if (changedText.length === 1) {
310
+ if (!isAllowed({
311
+ value: changedText,
312
+ allowed: inputs.allowedInputs,
313
+ blocked: inputs.blockedInputs,
314
+ })) {
315
+ // prevent the change from happening
316
+ finalText = beforeChangeText;
317
+ dispatch(new events.inputBlocked(changedText));
318
+ }
319
+ }
320
+ // filters out blocked pasted letters
321
+ else {
322
+ const { filtered, blocked } = filterToAllowedCharactersOnly({
323
+ value: changedText,
324
+ allowed: inputs.allowedInputs,
325
+ blocked: inputs.blockedInputs,
326
+ });
327
+ finalText = filtered;
328
+ dispatch(new events.inputBlocked(blocked));
329
+ }
330
+ }
331
+ if (inputElement.value !== finalText) {
332
+ // this prevents blocked inputs by simply overwriting them
333
+ inputElement.value = finalText;
334
+ }
335
+ if (beforeChangeText !== finalText) {
336
+ dispatch(new events.valueChange(finalText));
337
+ }
338
+ })}
339
+ placeholder=${inputs.placeholder}
340
+ />
341
+ ${(0, element_vir_1.renderIf)(!!inputs.suffix, (0, element_vir_1.html) `
342
+ <div class="suffix">${inputs.suffix}</div>
343
+ `)}
344
+ <!--
345
+ These separate style elements are necessary so that we can select them as
346
+ siblings of the focused <input> element.
347
+ -->
348
+ <div class="border-style focus-border"></div>
349
+ <div class="border-style label-border"></div>
350
+ </label>
351
+ `;
352
+ },
353
+ });
@@ -8,14 +8,16 @@ exports.Element16Icon = (0, icon_svg_1.defineIcon)({
8
8
  svgTemplate: (0, element_vir_1.html) `
9
9
  <svg
10
10
  xmlns="http://www.w3.org/2000/svg"
11
- xml:space="preserve"
12
11
  fill="none"
13
12
  width="16"
14
13
  height="16"
15
14
  viewBox="0 0 16 16"
16
- stroke-width="1px"
17
15
  >
18
- <path d="M4 5 1 8l3 3m8-6 3 3-3 3m-5 0 2-6" />
16
+ <path
17
+ stroke-width="1"
18
+ vector-effect="non-scaling-stroke"
19
+ d="M4 5 1 8l3 3m8-6 3 3-3 3m-5 0 2-6"
20
+ />
19
21
  </svg>
20
22
  `,
21
23
  });
@@ -8,14 +8,12 @@ exports.Element24Icon = (0, icon_svg_1.defineIcon)({
8
8
  svgTemplate: (0, element_vir_1.html) `
9
9
  <svg
10
10
  xmlns="http://www.w3.org/2000/svg"
11
- xml:space="preserve"
12
11
  viewBox="0 0 24 24"
13
12
  fill="none"
14
13
  width="24"
15
14
  height="24"
16
- stroke-width="1px"
17
15
  >
18
- <path d="m7 7-5 5 5 5M17 7l5 5-5 5m-6 0 2-10" />
16
+ <path stroke-width="1px" d="m7 7-5 5 5 5M17 7l5 5-5 5m-6 0 2-10" />
19
17
  </svg>
20
18
  `,
21
19
  });
@@ -1,5 +1,6 @@
1
1
  export declare const viraFocusCssVars: import("lit-css-vars").CssVarDefinitions<{
2
2
  'vira-focus-outline-color': string;
3
+ 'vira-focus-outline-border-radius': import("element-vir").CSSResult;
3
4
  }>;
4
5
  /**
5
6
  * Create styles that look like an outline for the given selector.
@@ -17,4 +18,5 @@ export declare function createFocusStyles({ mainSelector, elementBorderSize, out
17
18
  elementBorderSize: number;
18
19
  outlineGap?: number;
19
20
  outlineWidth?: number;
21
+ borderRadius?: number;
20
22
  }): import("element-vir").CSSResult;
@@ -5,8 +5,10 @@ const element_vir_1 = require("element-vir");
5
5
  const lit_1 = require("lit");
6
6
  const lit_css_vars_1 = require("lit-css-vars");
7
7
  const number_1 = require("../util/number");
8
+ const vira_css_vars_1 = require("./vira-css-vars");
8
9
  exports.viraFocusCssVars = (0, lit_css_vars_1.defineCssVars)({
9
10
  'vira-focus-outline-color': 'blue',
11
+ 'vira-focus-outline-border-radius': (0, element_vir_1.css) `calc(${vira_css_vars_1.viraCssVars['vira-form-input-border-radius'].value} + 4px)`,
10
12
  });
11
13
  /**
12
14
  * Create styles that look like an outline for the given selector.
@@ -27,7 +29,7 @@ function createFocusStyles({ mainSelector, elementBorderSize, outlineGap = 2, ou
27
29
  box-sizing: border-box;
28
30
  pointer-events: none;
29
31
  border: ${outlineWidth}px solid ${exports.viraFocusCssVars['vira-focus-outline-color'].value};
30
- border-radius: 12px;
32
+ border-radius: ${exports.viraFocusCssVars['vira-focus-outline-border-radius'].value};
31
33
  z-index: 100;
32
34
  }
33
35
  `;
@@ -9,7 +9,6 @@ exports.removeNativeFormStyles = (0, element_vir_1.css) `
9
9
  border: none;
10
10
  font: inherit;
11
11
  color: inherit;
12
- cursor: pointer;
13
12
  text-transform: inherit;
14
13
  text-decoration: inherit;
15
14
  -webkit-tap-highlight-color: transparent;
@@ -0,0 +1,3 @@
1
+ export declare const viraCssVars: import("lit-css-vars").CssVarDefinitions<{
2
+ 'vira-form-input-border-radius': string;
3
+ }>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.viraCssVars = void 0;
4
+ const lit_css_vars_1 = require("lit-css-vars");
5
+ exports.viraCssVars = (0, lit_css_vars_1.defineCssVars)({
6
+ 'vira-form-input-border-radius': '8px',
7
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/electrovir/vira",