Skip to content

Commit

Permalink
Merge pull request #112 from WJSoftware:JP/Column_Features_Demo
Browse files Browse the repository at this point in the history
feat(demo): Add per-column features demonstration
  • Loading branch information
webJose authored Aug 17, 2024
2 parents d7e8424 + b95b376 commit 8e9b30b
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 104 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"!dist/**/*.spec.*"
],
"peerDependencies": {
"svelte": "^5.0.0-next.205"
"svelte": "^5.0.0-next.223"
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.4",
Expand Down
12 changes: 9 additions & 3 deletions src/app.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
.btn-neutral {
--bs-neutral-btn-hover-color: 0, 0, 0;
--bs-neutral-btn-hover-opacity: 0.07;
--bs-neutral-btn-hover-opacity: 0.11;
--bs-neutral-btn-active-opacity: 0.07;
border: none;

[data-bs-theme="dark"] & {
--bs-neutral-btn-hover-color: 255, 255, 255;
--bs-neutral-btn-hover-opacity: 0.07;
--bs-neutral-btn-hover-opacity: 0.14;
--bs-neutral-btn-active-opacity: 0.07;
}

&:hover, &.hover {
&.active, .btn-check:checked+& {
background-color: rgba(var(--bs-neutral-btn-hover-color), var(--bs-neutral-btn-active-opacity));
}
&:hover, .btn-check+&:hover, &.hover, .btn-check+&.hover, &:focus, &.focus, .btn-check:focus+& {
background-color: rgba(var(--bs-neutral-btn-hover-color), var(--bs-neutral-btn-hover-opacity));
}
}
34 changes: 34 additions & 0 deletions src/demolib/AllColumnsDropdown.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import ColumnList, { type Column } from "./ColumnList.svelte";
import GlassyDropdownMenu from "./GlassyDropdownMenu.svelte";
type Props = {
columns: Column[];
};
let {
columns = $bindable(),
}: Props = $props();
let btn: HTMLButtonElement;
function getDd() {
return (globalThis as any).bootstrap.Dropdown.getInstance(btn);
}
</script>
<div class="dropdown">
<button
class="btn btn-neutral btn-sm"
type="button"
data-bs-toggle="dropdown"
title="Columns"
aria-expanded="false"
data-bs-auto-close="false"
bind:this={btn}
>
<i class="bi bi-layout-sidebar-inset"></i>
</button>
<GlassyDropdownMenu shadow>
<ColumnList bind:columns onClose={() => getDd().hide()} />
</GlassyDropdownMenu>
</div>
80 changes: 80 additions & 0 deletions src/demolib/ColumnList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<script context="module" lang="ts">
export type Column = { key: string; text: string; hidden?: boolean };
</script>

<script lang="ts">
import { nextControlId } from '$lib/utils.js';
type Props = {
columns: Column[];
newColumnThreshold?: number;
maxColumns?: number;
onClose?: () => void;
};
let { columns = $bindable(), newColumnThreshold = 5, maxColumns = 4, onClose }: Props = $props();
let thisId = nextControlId();
let numColumns = $derived(
Math.min(
maxColumns,
Math.floor(columns.length / newColumnThreshold) + (columns.length % newColumnThreshold !== 0 ? 1 : 0),
),
);
let numRows = $derived(Math.floor(columns.length / numColumns) + (columns.length % numColumns !== 0 ? 1 : 0));
function onInputHandler(col: Column, checked: boolean) {
col.hidden = !checked;
}
</script>

<div class="d-flex flex-row flex-nowrap px-4 pt-2 align-items-baseline">
<h6 class="me-3">Available Columns</h6>
<button
type="button"
class="btn btn-sm btn-secondary ms-auto me-2"
onclick="{() => columns.forEach((c) => (c.hidden = false))}">Select all</button
>
<button type="button" class="btn-close align-self-center" aria-label="Close" onclick="{() => onClose?.()}"></button>
</div>
<div class="px-4 py-2">
<table class="table table-sm table-borderless">
<tbody>
{#each { length: numRows } as _, rowIndex}
<tr>
{#each { length: numColumns } as _, colIndex}
{@const remainder = columns.length % numColumns}
{@const remainderConsumed = colIndex >= remainder}
{@const col =
remainderConsumed && remainder > 0 && rowIndex + 1 === numRows
? undefined
: columns[
(remainderConsumed ? remainder : colIndex) * numRows +
(remainderConsumed ? colIndex - remainder : 0) *
(numRows - (remainder > 0 ? 1 : 0)) +
rowIndex
]}
<td>
{#if col}
<input
type="checkbox"
class="form-check-input"
id="{thisId}_{col.key}"
checked="{!col.hidden}"
oninput="{(ev) => onInputHandler(col, ev.currentTarget.checked)}"
/>
<label for="{thisId}_{col.key}" class="me-3">{col.text}</label>
{/if}
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>

<style>
table {
--bs-table-bg: transparent;
}
</style>
29 changes: 29 additions & 0 deletions src/demolib/FavButtonMenuItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import { combineClasses } from "$lib/utils.js";
import type { Snippet } from "svelte";
import FavMenuItem from "./FavMenuItem.svelte";
type Props = {
pinPreference: boolean | undefined;
class?: string;
children: Snippet;
onClick?: () => void;
};
let {
pinPreference = $bindable(),
class: cssClass,
children,
onClick,
}: Props = $props();
</script>

<FavMenuItem bind:pinPreference>
<button
type="button"
class={combineClasses("btn btn-neutral rounded-0 text-start flex-fill pe-4", cssClass)}
onclick={() => onClick?.()}
>
{@render children()}
</button>
</FavMenuItem>
29 changes: 29 additions & 0 deletions src/demolib/FavMenuItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import { nextControlId } from "$lib/utils.js";
import type { Snippet } from "svelte";
type Props = {
pinPreference: boolean | undefined;
noMenuItem?: boolean;
children: Snippet;
};
let {
pinPreference = $bindable(),
noMenuItem = false,
children,
}: Props = $props();
let thisId = nextControlId();
</script>

<div class="d-flex flex-row p-0" class:dropdown-item={!noMenuItem}>
{@render children()}
<input type="checkbox" class="btn-check" bind:checked={pinPreference} id="{thisId}_pinpref">
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<label for="{thisId}_pinpref" class="btn btn-neutral rounded-0 flex-grow-0" onclick={(e) => e.stopPropagation()}>
<!-- <i class="bi bi-{pinPreference ? 'star-fill' : 'star'}"></i> -->
<i class="bi bi-stars"></i>
</label>
</div>
26 changes: 26 additions & 0 deletions src/demolib/GlassyDropdownMenu.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import type { Snippet } from "svelte";
import type { HTMLAttributes } from "svelte/elements";
type Props = HTMLAttributes<HTMLDivElement> & {
children?: Snippet;
shadow?: boolean;
};
let {
children,
shadow,
...restProps
}: Props = $props();
</script>

<div class="dropdown-menu bg-glass" class:shadow {...restProps}>
{@render children?.()}
</div>

<style lang="scss">
.bg-glass {
background-color: rgba(var(--bs-body-bg-rgb), 0.3);
backdrop-filter: blur(7px) saturate(110%);
}
</style>
Loading

0 comments on commit 8e9b30b

Please sign in to comment.