Skip to content

Commit

Permalink
Merge pull request #2450 from skeletonlabs/dev
Browse files Browse the repository at this point in the history
Merge for release - Jan 30, 2024
  • Loading branch information
endigo9740 authored Jan 30, 2024
2 parents 765e876 + 6e0c3db commit 93a9773
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 55 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-pots-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@skeletonlabs/skeleton": patch
---

bugfix: Removed recursive-tree-view's unused props for `disabled` and `open`
5 changes: 5 additions & 0 deletions .changeset/flat-icons-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@skeletonlabs/skeleton": minor
---

feat: InputChips now allow you to add/remove chips programatically.
5 changes: 5 additions & 0 deletions .changeset/nasty-terms-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@skeletonlabs/skeleton": patch
---

bugfix: CodeBlock copy button type is now `button` instead of default (`submit`)
5 changes: 5 additions & 0 deletions .changeset/real-cougars-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@skeletonlabs/skeleton": patch
---

bugfix: added `label` prop to InputChips to provide aria-label for a11y
5 changes: 5 additions & 0 deletions .changeset/swift-insects-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@skeletonlabs/skeleton": patch
---

chore: Applied `@html` interpretation to Autocomplete empty state
2 changes: 1 addition & 1 deletion packages/plugin/src/styles/components/modals.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}

/* Provides initial focus selection styles on opening the modal */
.modal *:focus:not([tabindex='-1']):not(.input):not(.textarea):not(.select):not(.input-group) {
.modal *:focus:not([tabindex='-1']):not(.input):not(.textarea):not(.select):not(.input-group):not(.input-group input) {
outline-style: auto;
@apply outline-[-webkit-focus-ring-color];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,6 @@
</ul>
</nav>
{:else}
<div class="autocomplete-empty {classesEmpty}">{emptyState}</div>
<div class="autocomplete-empty {classesEmpty}">{@html emptyState}</div>
{/if}
</div>
115 changes: 79 additions & 36 deletions packages/skeleton/src/lib/components/InputChip/InputChip.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
type InputChipEvent = {
add: { event: SubmitEvent; chipIndex: number; chipValue: string };
remove: { event: MouseEvent; chipIndex: number; chipValue: string };
addManually: { chipIndex: number; chipValue: string };
removeManually: { chipValue: string };
invalid: { event: SubmitEvent; input: string };
invalidManually: { input: string };
};
const dispatch = createEventDispatcher<InputChipEvent>();
Expand Down Expand Up @@ -86,6 +89,10 @@
/** Provide arbitrary classes to style the input field region. */
export let regionInput: CssClasses = '';
// Props (A11y)
/** Provide the ARIA label for the select input. */
export let label = 'Chips select';
// Props (transition)
/**
* Enable/Disable transitions
Expand Down Expand Up @@ -170,27 +177,53 @@
inputValid = true;
}
function validate(): boolean {
if (!input) return false;
function validateCustom(chip: string) {
return validation === undefined || validation(chip);
}
function validateCount() {
return max === -1 || value.length < max;
}
function validateLength(chip: string) {
return (minlength === -1 || chip.length >= minlength) && (maxlength === -1 || chip.length <= maxlength);
}
function validateWhiteList(chip: string) {
return whitelist.length === 0 || whitelist.includes(chip);
}
function validateDuplicates(chip: string) {
return allowDuplicates || !value.includes(chip);
}
function validate(chip: string = ''): boolean {
if (!chip && !input) return false;
// Format: trim value
input = input.trim();
// Custom validation
if (validation !== undefined && !validation(input)) return false;
// Maximum
if (max !== -1 && value.length >= max) return false;
// Minimum Character Length
if (minlength !== -1 && input.length < minlength) return false;
// Maximum Character Length
if (maxlength !== -1 && input.length > maxlength) return false;
// Whitelist (if available)
if (whitelist.length > 0 && !whitelist.includes(input)) return false;
// Value is unique
if (allowDuplicates === false && value.includes(input)) return false;
// State is valid
return true;
chip = chip !== '' ? chip.trim() : input.trim();
return validateCustom(chip) && validateCount() && validateLength(chip) && validateWhiteList(chip) && validateDuplicates(chip);
}
function addChip(event: SvelteEvent<SubmitEvent, HTMLFormElement>): void {
function addChipCommon(chip: string) {
// Format: to lowercase (if enabled)
chip = allowUpperCase ? chip : chip.toLowerCase();
// Append value to array
value.push(chip);
value = value;
chipValues.push({ val: chip, id: Math.random() });
chipValues = chipValues;
}
function removeChipCommon(chip: string) {
let chipIndex = value.indexOf(chip);
// Remove value from array
value.splice(chipIndex, 1);
value = value;
chipValues.splice(chipIndex, 1);
chipValues = chipValues;
}
function addChipInternally(event: SvelteEvent<SubmitEvent, HTMLFormElement>): void {
event.preventDefault();
// Validate
inputValid = validate();
Expand All @@ -200,30 +233,42 @@
dispatch('invalid', { event, input });
return;
}
// Format: to lowercase (if enabled)
input = allowUpperCase ? input : input.toLowerCase();
// Append value to array
value.push(input);
value = value;
chipValues.push({ val: input, id: Math.random() });
chipValues = chipValues;
addChipCommon(input);
/** @event {{ event: Event, chipIndex: number, chipValue: string }} add - Fires when a chip is added. */
dispatch('add', { event, chipIndex: value.length - 1, chipValue: input });
// Clear input value
input = '';
}
function removeChip(event: SvelteEvent<MouseEvent, HTMLButtonElement>, chipIndex: number, chipValue: string): void {
function removeChipInternally(event: SvelteEvent<MouseEvent, HTMLButtonElement>, chipIndex: number, chipValue: string): void {
if ($$restProps.disabled) return;
// Remove value from array
value.splice(chipIndex, 1);
value = value;
chipValues.splice(chipIndex, 1);
chipValues = chipValues;
removeChipCommon(chipValue);
/** @event {{ event: Event, chipIndex: number, chipValue: string }} remove - Fires when a chip is removed. */
dispatch('remove', { event, chipIndex, chipValue });
}
// Export functions
export function addChip(chip: string) {
// Validate
inputValid = validate(chip);
// When the onInvalid hook is present
if (inputValid === false) {
/** @event {{ input: string }} invalidManually - Fires when the manually added value is invalid. */
dispatch('invalidManually', { input: chip });
return;
}
addChipCommon(chip);
/** @event {{ chipIndex: number, chipValue: string }} addManually - Fires when a chip is added manually. */
dispatch('addManually', { chipIndex: value.length - 1, chipValue: chip });
}
export function removeChip(chip: string) {
if ($$restProps.disabled) return;
removeChipCommon(chip);
/** @event {{ chipValue: string }} removeManually - Fires when a chip is removed manually. */
dispatch('removeManually', { chipValue: chip });
}
// State
$: classesInvalid = inputValid === false ? invalid : '';
// Reactive
Expand All @@ -241,15 +286,15 @@
<div class="input-chip {classesBase}" class:opacity-50={$$restProps.disabled}>
<!-- NOTE: Don't use `hidden` as it prevents `required` from operating -->
<div class="h-0 overflow-hidden">
<select bind:this={selectElement} bind:value {name} multiple {required} tabindex="-1">
<select bind:this={selectElement} bind:value {name} multiple {required} aria-label={label} tabindex="-1">
<!-- NOTE: options are required! -->
{#each value as option}<option value={option}>{option}</option>{/each}
</select>
</div>
<!-- Chip Wrapper -->
<div class="input-chip-wrapper {classesChipWrapper}">
<!-- Input Field -->
<form on:submit={addChip}>
<form on:submit={addChipInternally}>
<input
type="text"
bind:value={input}
Expand All @@ -275,9 +320,7 @@
<button
type="button"
class="chip {chips}"
on:click={(e) => {
removeChip(e, i, val);
}}
on:click={(e) => removeChipInternally(e, i, val)}
on:click
on:keypress
on:keydown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@
export let spacing: CssClasses = 'space-y-1';
// Props (children)
/** Set open by default on load. */
export let open = false;
/** Set the tree disabled state */
export let disabled = false;
/** Provide classes to set the tree item padding styles. */
export let padding: CssClasses = 'py-4 px-4';
/** Provide classes to set the tree children indentation */
Expand Down Expand Up @@ -77,11 +73,9 @@
export let labelledby = '';
// Context API
setContext('open', open);
setContext('selection', selection);
setContext('multiple', multiple);
setContext('relational', relational);
setContext('disabled', disabled);
setContext('padding', padding);
setContext('indent', indent);
setContext('hover', hover);
Expand Down Expand Up @@ -114,14 +108,7 @@
$: classesBase = `${width} ${spacing} ${$$props.class ?? ''}`;
</script>

<div
class="tree {classesBase}"
data-testid="tree"
role="tree"
aria-multiselectable={multiple}
aria-label={labelledby}
aria-disabled={disabled}
>
<div class="tree {classesBase}" data-testid="tree" role="tree" aria-multiselectable={multiple} aria-label={labelledby}>
{#if nodes && nodes.length > 0}
<RecursiveTreeViewItem
{nodes}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
<!-- Language -->
<span class="codeblock-language">{languageFormatter(language)}</span>
<!-- Copy Button -->
<button class="codeblock-btn {button}" on:click={onCopyClick} use:clipboard={code}>
<button type="button" class="codeblock-btn {button}" on:click={onCopyClick} use:clipboard={code}>
{!copyState ? buttonLabel : buttonCopied}
</button>
</header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
let emails = ['[email protected]', '[email protected]', '[email protected]'];
let musicalGenres = ['rock', 'r&b', 'pop'];
let musicalGenresWhitelist = ['rock', 'pop', 'hip-hop', 'metal', 'techno', 'r&b'];
let manualList: string[] = [];
let manualInputChip: InputChip;
const toastStore = getToastStore();
function isValidEmail(value: string): boolean {
Expand Down Expand Up @@ -161,6 +163,50 @@ function onInvalidHandler(event: any): void {
</svelte:fragment>
</DocsPreview>
</section>
<!-- Add/Remove Chips Programatically -->
<section class="space-y-4">
<h2 class="h2">Add / Remove Chips</h2>
<p>
To add or remove chips programatically, use the exported functions <code class="code">addChip</code> and
<code class="code">removeChip</code> after binding the ChipInput.
</p>
<DocsPreview background="neutral">
<svelte:fragment slot="preview">
<InputChip
bind:this={manualInputChip}
bind:value={manualList}
name="chips-example-programatic"
placeholder="Enter number..."
chips="variant-filled-tertiary"
/>
</svelte:fragment>
<svelte:fragment slot="footer">
<div class="text-center">
<button type="button" class="btn variant-filled" on:click={() => manualInputChip.removeChip(manualList[-1])}
>Remove LastChip</button
>
<button
type="button"
class="btn variant-filled"
on:click={() => manualInputChip.addChip((Math.floor(Math.random() * 10000) + 1).toString())}>Add Random Number</button
>
</div>
</svelte:fragment>
<svelte:fragment slot="source">
<CodeBlock
language="ts"
code={`
let inputChip: InputChip;
// add chip manually
inputChip.addChip('chipValue');
// remove chip manually
inputChip.removeChip('chipValue');
`}
/>
<CodeBlock language="html" code={`<InputChip ... bind:this={inputChip} />`} />
</svelte:fragment>
</DocsPreview>
</section>
<!-- Additional Settings -->
<section class="space-y-4">
<h2 class="h2">Additional Settings</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
<svelte:fragment slot="source">
<CodeBlock
language="html"
code={`<ProgressRadial ... stroke={${strokeProps.value}} meter="stroke-primary-500" track="stroke-primary-500/30" strokeLinecap={${strokeLinecap}} />`}
code={`<ProgressRadial ... stroke={${strokeProps.value}} meter="stroke-primary-500" track="stroke-primary-500/30" strokeLinecap="${strokeLinecap}" />`}
/>
</svelte:fragment>
</DocsPreview>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ const popupState: PopupSettings = {
<span class="capitalize">{comboboxValue ?? 'Trigger'}</span>
<i class="fa-solid fa-caret-down opacity-50" />
</button>
<div class="card w-48 shadow-xl py-2" data-popup="popupCombobox">
<div class="card w-48 shadow-xl py-2 overflow-hidden" data-popup="popupCombobox">
<ListBox rounded="rounded-none">
<ListBoxItem bind:group={comboboxValue} name="medium" value="books">Books</ListBoxItem>
<ListBoxItem bind:group={comboboxValue} name="medium" value="movies">Movies</ListBoxItem>
Expand Down

0 comments on commit 93a9773

Please sign in to comment.