@winkintel/bootstrap-svelte 1.0.7 → 1.0.10

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.
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Bootstrap Svelte
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@winkintel/bootstrap-svelte.svg)](https://www.npmjs.com/package/@winkintel/bootstrap-svelte)
4
+ [![weekly downloads](https://img.shields.io/npm/dw/@winkintel/bootstrap-svelte.svg)](https://www.npmjs.com/package/@winkintel/bootstrap-svelte)
5
+ [![CI](https://github.com/WinkIntel/bootstrap-svelte/actions/workflows/ci.yml/badge.svg)](https://github.com/WinkIntel/bootstrap-svelte/actions/workflows/ci.yml)
6
+ [![license](https://img.shields.io/npm/l/@winkintel/bootstrap-svelte.svg)](https://github.com/WinkIntel/bootstrap-svelte/blob/main/LICENSE.md)
7
+ [![documentation](https://img.shields.io/badge/docs-bootstrap--svelte.vercel.app-7952b3.svg)](https://bootstrap-svelte.vercel.app/)
8
+
3
9
  > Bootstrap 5 components for Svelte 5 with TypeScript support.
4
10
 
5
11
  Bootstrap Svelte provides ready-to-use, type-safe Bootstrap components for Svelte 5 applications. It follows Bootstrap's design language and class conventions while exposing Svelte-native component APIs.
@@ -8,11 +14,21 @@ Use it when you want Bootstrap's familiar grid, utilities, and UI patterns in a
8
14
 
9
15
  ## Links
10
16
 
17
+ - Documentation: <https://bootstrap-svelte.vercel.app/>
11
18
  - npm: [`@winkintel/bootstrap-svelte`](https://www.npmjs.com/package/@winkintel/bootstrap-svelte)
12
19
  - Repository: [`WinkIntel/bootstrap-svelte`](https://github.com/WinkIntel/bootstrap-svelte)
13
20
  - Bootstrap: <https://getbootstrap.com/>
14
21
  - Svelte: <https://svelte.dev/>
15
22
 
23
+ ## Machine-readable documentation
24
+
25
+ The showcase at <https://bootstrap-svelte.vercel.app> is published for AI agents and tools as well as people:
26
+
27
+ - `/llms.txt` indexes every page with one-line summaries ([llms.txt format](https://llmstxt.org)); `/llms-full.txt` bundles every page into one Markdown file.
28
+ - Every page is available as Markdown from its own URL with `Accept: text/markdown` (quality values are honored; the response carries `Vary: Accept` and a `Link` alternate header), or by appending `.md` to the path, for example `/components/button.md`.
29
+ - `/agents.md` explains when to use the library and how to integrate it; `/sitemap.xml` and `/robots.txt` serve crawlers.
30
+ - Paths that do not exist return a real HTTP 404 with a Markdown or HTML body that links back to the documentation index.
31
+
16
32
  ## Why this exists
17
33
 
18
34
  Bootstrap is still a practical choice for many product, enterprise, and internal applications: it is familiar, well documented, stable, and easy for mixed frontend/backend teams to work with.
@@ -51,11 +67,7 @@ yarn add @winkintel/bootstrap-svelte bootstrap
51
67
 
52
68
  ### Peer dependency
53
69
 
54
- This package requires Svelte 5:
55
-
56
- ```bash
57
- pnpm add svelte@^5.29.0
58
- ```
70
+ This package requires Svelte `^5.29.0` as a peer dependency. Keep Svelte installed in your application; do not replace the package/bootstrap install command with a Svelte install command.
59
71
 
60
72
  ## Bootstrap CSS
61
73
 
@@ -82,23 +94,19 @@ Or use Bootstrap SCSS from your app stylesheet/build pipeline:
82
94
  let showModal = $state(false);
83
95
  </script>
84
96
 
85
- <Alert colorVariant="primary" isDismissible>
86
- Welcome to Bootstrap Svelte!
87
- </Alert>
97
+ <Alert colorVariant="primary" isDismissible>Welcome to Bootstrap Svelte!</Alert>
88
98
 
89
- <Card>
99
+ <Card.Root>
90
100
  <Card.Header>
91
101
  <Card.Title>Getting Started</Card.Title>
92
102
  </Card.Header>
93
103
  <Card.Body>
94
104
  <Card.Text>This is a card built with Bootstrap Svelte components.</Card.Text>
95
- <Button colorVariant="primary" onclick={() => (showModal = true)}>
96
- Open Modal
97
- </Button>
105
+ <Button colorVariant="primary" onclick={() => (showModal = true)}>Open Modal</Button>
98
106
  </Card.Body>
99
- </Card>
107
+ </Card.Root>
100
108
 
101
- <Modal isShown={showModal}>
109
+ <Modal.Root isShown={showModal}>
102
110
  <Modal.Dialog>
103
111
  <Modal.Content>
104
112
  <Modal.Header>
@@ -106,13 +114,11 @@ Or use Bootstrap SCSS from your app stylesheet/build pipeline:
106
114
  </Modal.Header>
107
115
  <Modal.Body>Modal content goes here.</Modal.Body>
108
116
  <Modal.Footer>
109
- <Button colorVariant="secondary" onclick={() => (showModal = false)}>
110
- Close
111
- </Button>
117
+ <Button colorVariant="secondary" onclick={() => (showModal = false)}>Close</Button>
112
118
  </Modal.Footer>
113
119
  </Modal.Content>
114
120
  </Modal.Dialog>
115
- </Modal>
121
+ </Modal.Root>
116
122
  ```
117
123
 
118
124
  ## Available components
@@ -174,7 +180,7 @@ Interactive components are implemented as Svelte components rather than requirin
174
180
 
175
181
  ## Status and feedback
176
182
 
177
- This package is published as `1.0.7`, but feedback from Svelte developers is still very welcome. Useful feedback includes:
183
+ This package is published as `1.0.10`, but feedback from Svelte developers is still very welcome. Useful feedback includes:
178
184
 
179
185
  - Component API ergonomics
180
186
  - Svelte 5 idioms and runes compatibility
@@ -21,14 +21,16 @@ The container for dropdown items.
21
21
  - `isDark` (boolean): Optional. Makes the dropdown menu dark-themed, default is false.
22
22
  - `isEnd` (boolean): Optional. Aligns the dropdown menu to the end of its parent, default is false.
23
23
  - `offset` (number[]): Optional. Offset for the dropdown menu position, default is `[0, 2]`.
24
+ - `onkeydown` (EventListener): Optional. Keydown handler, called after the menu's own Escape dismissal.
24
25
  -->
25
26
  <script lang="ts">import { uniqueClsx } from '../common/css.js';
27
+ import { noop } from '../common/noop.js';
26
28
  import { Portal } from '../index.js';
27
29
  import { onMount } from 'svelte';
28
30
  import { DropdownMenuState, initDropdownMenuState } from './dropdown.svelte.js';
29
31
  // Generate a unique ID for the dropdown menu
30
32
  const uid = $props.id();
31
- let { children, class: classValues, container = false, elementRef = $bindable(null), id = `dropdown-menu-${uid}`, isDark = false, isEnd = false, offset = [0, 2], ...restOfProps } = $props();
33
+ let { children, class: classValues, container = false, elementRef = $bindable(null), id = `dropdown-menu-${uid}`, isDark = false, isEnd = false, offset = [0, 2], onkeydown = noop, ...restOfProps } = $props();
32
34
  let containerElement = $derived(container === false ? 'body' : container);
33
35
  const menuState = initDropdownMenuState({
34
36
  get elementRef() {
@@ -63,9 +65,14 @@ $effect(() => {
63
65
  $effect(() => {
64
66
  menuState.isEnd = isEnd;
65
67
  });
68
+ const handleKeydown = (event) => {
69
+ menuState.onkeydown(event);
70
+ onkeydown(event);
71
+ };
66
72
  </script>
67
73
 
68
74
  <svelte:body onclick={menuState.bodyOnclick} />
75
+ <svelte:window onkeyup={menuState.windowOnkeyup} />
69
76
 
70
77
  <Portal target={containerElement} disabled={container === false}>
71
78
  <ul
@@ -75,6 +82,7 @@ $effect(() => {
75
82
  data-bs-popper={menuState.isShown && menuState.root.isNavItem ? 'static' : undefined}
76
83
  data-popper-placement={menuState.popperPlacement}
77
84
  {id}
85
+ onkeydown={handleKeydown}
78
86
  role={menuState.root.hasItems ? 'menu' : undefined}
79
87
  {...restOfProps}>
80
88
  {@render children?.()}
@@ -21,6 +21,7 @@ import type { Dropdown } from './index.js';
21
21
  * - `isDark` (boolean): Optional. Makes the dropdown menu dark-themed, default is false.
22
22
  * - `isEnd` (boolean): Optional. Aligns the dropdown menu to the end of its parent, default is false.
23
23
  * - `offset` (number[]): Optional. Offset for the dropdown menu position, default is `[0, 2]`.
24
+ * - `onkeydown` (EventListener): Optional. Keydown handler, called after the menu's own Escape dismissal.
24
25
  */
25
26
  declare const DropdownMenu: import("svelte").Component<Dropdown.MenuProps, {}, "elementRef">;
26
27
  type DropdownMenu = ReturnType<typeof DropdownMenu>;
@@ -28,6 +28,9 @@ import { DropdownToggleState, initDropdownToggleState } from './dropdown.svelte.
28
28
  const uid = $props.id();
29
29
  let { children, class: classValues, colorVariant, disabled = false, elementRef = $bindable(null), href, id = `dropdown-toggle-${uid}`, isSplit = false, onclick = noop, onkeydown = noop, size, type, ...restOfProps } = $props();
30
30
  const toggleState = initDropdownToggleState({
31
+ get elementRef() {
32
+ return elementRef;
33
+ },
31
34
  get id() {
32
35
  return id;
33
36
  },
@@ -13,7 +13,9 @@ export class DropdownRootState {
13
13
  #isNavItem = $state(false);
14
14
  #isShown = $state(false);
15
15
  #items = $state([]);
16
+ #menu = null; // The menu belonging to this dropdown, registered on construction.
16
17
  #reorderScheduled = false;
18
+ #toggle = null; // The toggle that controls this dropdown, registered on construction.
17
19
  ariaLabelledBy = $state(undefined); // Used for accessibility, linking the dropdown to a label.
18
20
  constructor(props) {
19
21
  this.props = props;
@@ -25,6 +27,8 @@ export class DropdownRootState {
25
27
  // Bind the method to ensure `this` context is correct when passed as a callback.
26
28
  this.focusOnNextItem = this.focusOnNextItem.bind(this);
27
29
  this.focusOnPreviousItem = this.focusOnPreviousItem.bind(this);
30
+ this.focusOnToggle = this.focusOnToggle.bind(this);
31
+ this.hide = this.hide.bind(this);
28
32
  this.registerItem = this.registerItem.bind(this);
29
33
  this.reorderItems = this.reorderItems.bind(this);
30
34
  this.scheduleReorderItems = this.scheduleReorderItems.bind(this);
@@ -82,12 +86,43 @@ export class DropdownRootState {
82
86
  get isShown() {
83
87
  return this.#isShown;
84
88
  }
89
+ get menu() {
90
+ return this.#menu;
91
+ }
92
+ set menu(menu) {
93
+ this.#menu = menu;
94
+ }
95
+ get toggle() {
96
+ return this.#toggle;
97
+ }
98
+ set toggle(toggle) {
99
+ this.#toggle = toggle;
100
+ }
101
+ // True when the given element is part of this dropdown — its root (toggle included)
102
+ // or its menu, which may be portaled outside the root via the menu's `container` prop.
103
+ containsElement(element) {
104
+ if (!element) {
105
+ return false;
106
+ }
107
+ return Boolean(this.#elementRef?.contains(element) || this.#menu?.elementRef?.contains(element));
108
+ }
85
109
  focusOnNextItem() {
86
110
  this.focusOnItemInDirection(1);
87
111
  }
88
112
  focusOnPreviousItem() {
89
113
  this.focusOnItemInDirection(-1);
90
114
  }
115
+ focusOnToggle() {
116
+ this.#toggle?.props.elementRef?.focus();
117
+ }
118
+ // Closes the dropdown if it is open, firing the onHide/onHidden callbacks.
119
+ // Unlike toggleIsShown this is a no-op when the dropdown is already closed.
120
+ hide(event) {
121
+ if (!this.#isShown) {
122
+ return;
123
+ }
124
+ this.toggleIsShown(event);
125
+ }
91
126
  registerItem(item) {
92
127
  item.itemIndex = this.#items.length; // Set the item's index based on current length.
93
128
  this.#items = [...this.#items, item];
@@ -174,6 +209,7 @@ export class DropdownToggleState {
174
209
  // Bind the method to ensure `this` context is correct when used as an event handler.
175
210
  this.onclick = this.onclick.bind(this);
176
211
  this.onkeydown = this.onkeydown.bind(this);
212
+ this.root.toggle = this; // Let the root find the toggle again, e.g. to restore focus on Escape.
177
213
  if (this.props.isSplit && !this.root.isButtonGroup) {
178
214
  // If the toggle is a split button, the root must be treated as a button group
179
215
  // to ensure correct Bootstrap styling and layout.
@@ -215,7 +251,10 @@ export class DropdownMenuState {
215
251
  this.destroyPopper = this.destroyPopper.bind(this);
216
252
  this.determinePopperPlacement = this.determinePopperPlacement.bind(this);
217
253
  this.dispose = this.dispose.bind(this);
254
+ this.onkeydown = this.onkeydown.bind(this);
218
255
  this.syncIsEndWithRoot = this.syncIsEndWithRoot.bind(this);
256
+ this.windowOnkeyup = this.windowOnkeyup.bind(this);
257
+ this.root.menu = this; // Let the root reach the menu element, which may be portaled outside the root.
219
258
  // Ensure the dropdown menu's end alignment is consistent with the root's direction.
220
259
  this.syncIsEndWithRoot();
221
260
  // Effect to manage the Popper.js instance lifecycle.
@@ -274,9 +313,38 @@ export class DropdownMenuState {
274
313
  this.root.toggleIsShown(event);
275
314
  }
276
315
  }
316
+ // Backstop for Escape pressed on focusable content inside the menu that is not a
317
+ // Dropdown.Item — a form input, a plain link, a consumer's own button. Items and the
318
+ // toggle consume Escape before it can bubble this far, so this never double-handles.
319
+ onkeydown(event) {
320
+ if (event.key !== 'Escape') {
321
+ return;
322
+ }
323
+ handleEscape(event, this.root);
324
+ }
325
+ // Closes the dropdown once Tab has moved focus out of it. Handled on keyup rather than
326
+ // keydown because focus has not moved yet while the key is down, and at window level
327
+ // because the newly focused element is usually outside this component's markup.
328
+ windowOnkeyup(event) {
329
+ if (!this.isShown || event.key !== 'Tab') {
330
+ return;
331
+ }
332
+ if (this.root.containsElement(document.activeElement)) {
333
+ // Focus moved between items inside the dropdown, so it stays open.
334
+ return;
335
+ }
336
+ // Tabbing away is an interaction outside the dropdown, so it follows the same
337
+ // autoClose rules as an outside click.
338
+ if (this.autoClose === true || this.autoClose === 'outside') {
339
+ this.root.hide(event);
340
+ }
341
+ }
277
342
  // Cleans up resources, particularly the Popper.js instance and element references.
278
343
  dispose() {
279
344
  this.destroyPopper();
345
+ if (this.root.menu === this) {
346
+ this.root.menu = null;
347
+ }
280
348
  this.#elementRef = null;
281
349
  this.#rootElementRef = null; // Clearing derived state source if it were directly settable.
282
350
  this.#popperInstance = null;
@@ -449,15 +517,52 @@ export function initDropdownItemState(props) {
449
517
  rootState.registerItem(itemState);
450
518
  return itemState;
451
519
  }
520
+ /**
521
+ * Dismisses an open dropdown in response to Escape, returning focus to the toggle.
522
+ *
523
+ * Shared by the toggle, the items, and the menu itself. The menu is the backstop that
524
+ * catches Escape from focusable content a consumer renders inside it — inputs, links,
525
+ * arbitrary buttons — which are not Dropdown.Items and carry no handler of their own.
526
+ * Because the toggle and items stop a consumed Escape from propagating, the menu-level
527
+ * handler never sees the same key twice.
528
+ *
529
+ * Escape ignores autoClose: it is an explicit dismissal rather than an incidental one.
530
+ *
531
+ * @param event KeyboardEvent
532
+ * @param root DropdownRootState
533
+ */
534
+ function handleEscape(event, root) {
535
+ if (!root.isShown) {
536
+ return;
537
+ }
538
+ event.preventDefault();
539
+ // Stop the event here so an ancestor that also dismisses on Escape (a modal, an
540
+ // offcanvas, an app-level sidebar) does not close as well. Escape should unwind one
541
+ // layer at a time, which is what Bootstrap's own dropdown does.
542
+ //
543
+ // This covers listeners in the bubble path only. A listener bound on document or
544
+ // window in the *capture* phase runs before the event ever reaches the dropdown and
545
+ // cannot be stopped from here — notably Bootstrap's own data-API handlers, which are
546
+ // registered with capture. Loading Bootstrap's JS bundle alongside this package makes
547
+ // both implementations respond to the same markup and is not a supported setup.
548
+ event.stopPropagation();
549
+ root.hide(event);
550
+ root.focusOnToggle();
551
+ }
452
552
  /**
453
553
  * Handles keyboard navigation for the toggle and items within the dropdown.
454
- * Supports opening the dropdown with ArrowUp/ArrowDown and navigating between items.
554
+ * Supports opening the dropdown with ArrowUp/ArrowDown, navigating between items,
555
+ * and dismissing an open dropdown with Escape.
455
556
  *
456
557
  * @param event KeyboardEvent
457
558
  * @param root DropdownRootState
458
559
  */
459
560
  function handleKeydown(event, root) {
460
561
  const { key } = event;
562
+ if (key === 'Escape') {
563
+ handleEscape(event, root);
564
+ return;
565
+ }
461
566
  const isUpOrDownEvent = ['ArrowUp', 'ArrowDown'].includes(event.key);
462
567
  if (isUpOrDownEvent && !root.isShown) {
463
568
  event.preventDefault();
@@ -25,6 +25,7 @@ export type DropdownMenuProps = UListElement & {
25
25
  isDark?: boolean;
26
26
  isEnd?: boolean;
27
27
  offset?: PopperOffset;
28
+ onkeydown?: EventListener;
28
29
  };
29
30
  export type DropdownItemProps = AnchorElement & {
30
31
  href?: HTMLAnchorAttributes['href'];
@@ -13,12 +13,12 @@ Bootstrap-styled helper text component for providing additional information abou
13
13
  <Form.TextInput id="emailInput" placeholder="Enter your email" aria-describedby="email-help" />
14
14
  <Form.HelperText id="email-help">We'll never share your email with anyone else.</Form.HelperText>
15
15
 
16
- // Inside a form group
17
- <Form.Group>
16
+ // Inside an input group
17
+ <Form.InputGroup>
18
18
  <Form.InputLabel for="passwordInput">Password</Form.InputLabel>
19
19
  <Form.PasswordInput id="passwordInput" />
20
20
  <Form.HelperText>Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces or emoji.</Form.HelperText>
21
- </Form.Group>
21
+ </Form.InputGroup>
22
22
  ```
23
23
  ### Props
24
24
  - `class` (string): Optional. Additional CSS classes to apply to the helper text.
@@ -12,12 +12,12 @@
12
12
  * <Form.TextInput id="emailInput" placeholder="Enter your email" aria-describedby="email-help" />
13
13
  * <Form.HelperText id="email-help">We'll never share your email with anyone else.</Form.HelperText>
14
14
  *
15
- * // Inside a form group
16
- * <Form.Group>
15
+ * // Inside an input group
16
+ * <Form.InputGroup>
17
17
  * <Form.InputLabel for="passwordInput">Password</Form.InputLabel>
18
18
  * <Form.PasswordInput id="passwordInput" />
19
19
  * <Form.HelperText>Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces or emoji.</Form.HelperText>
20
- * </Form.Group>
20
+ * </Form.InputGroup>
21
21
  * ```
22
22
  * ### Props
23
23
  * - `class` (string): Optional. Additional CSS classes to apply to the helper text.
@@ -6,11 +6,11 @@ Bootstrap-styled label component for form input elements.
6
6
  @example
7
7
  ```svelte
8
8
  // Standard label for input
9
- <Form.Group>
9
+ <Form.InputGroup>
10
10
  <Form.InputLabel for="exampleInput">Email address</Form.InputLabel>
11
11
  <Form.EmailInput id="exampleInput" placeholder="name@example.com" />
12
12
  <Form.HelperText>We'll never share your email with anyone else.</Form.HelperText>
13
- </Form.Group>
13
+ </Form.InputGroup>
14
14
 
15
15
  // Floating label (used with Form.Floating)
16
16
  <Form.Floating>
@@ -6,11 +6,11 @@ import type { Form } from './index.js';
6
6
  * @example
7
7
  * ```svelte
8
8
  * // Standard label for input
9
- * <Form.Group>
9
+ * <Form.InputGroup>
10
10
  * <Form.InputLabel for="exampleInput">Email address</Form.InputLabel>
11
11
  * <Form.EmailInput id="exampleInput" placeholder="name@example.com" />
12
12
  * <Form.HelperText>We'll never share your email with anyone else.</Form.HelperText>
13
- * </Form.Group>
13
+ * </Form.InputGroup>
14
14
  *
15
15
  * // Floating label (used with Form.Floating)
16
16
  * <Form.Floating>
@@ -16,19 +16,19 @@ Bootstrap-styled range slider input component for selecting a value within a ran
16
16
  <Form.RangeInput disabled max="5" min="0" step="0.5" title="Set a number" value="1" />
17
17
 
18
18
  // With label and current value display
19
- <Form.Group>
19
+ <Form.InputGroup>
20
20
  <Form.InputLabel for="customRange">Example range</Form.InputLabel>
21
21
  <Form.RangeInput id="customRange" max="10" min="0" />
22
- </Form.Group>
22
+ </Form.InputGroup>
23
23
 
24
24
  // With steps and ticks
25
- <Form.Group>
25
+ <Form.InputGroup>
26
26
  <Form.InputLabel for="stepRange">Range with steps</Form.InputLabel>
27
27
  <Form.RangeInput id="stepRange" max="5" min="0" step="1" />
28
28
  <div class="d-flex justify-content-between">
29
29
  <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
30
30
  </div>
31
- </Form.Group>
31
+ </Form.InputGroup>
32
32
  ```
33
33
  ### Props
34
34
  - `class` (string): Optional. Additional CSS classes to apply to the range input.
@@ -16,19 +16,19 @@ import type { Form } from './index.js';
16
16
  * <Form.RangeInput disabled max="5" min="0" step="0.5" title="Set a number" value="1" />
17
17
  *
18
18
  * // With label and current value display
19
- * <Form.Group>
19
+ * <Form.InputGroup>
20
20
  * <Form.InputLabel for="customRange">Example range</Form.InputLabel>
21
21
  * <Form.RangeInput id="customRange" max="10" min="0" />
22
- * </Form.Group>
22
+ * </Form.InputGroup>
23
23
  *
24
24
  * // With steps and ticks
25
- * <Form.Group>
25
+ * <Form.InputGroup>
26
26
  * <Form.InputLabel for="stepRange">Range with steps</Form.InputLabel>
27
27
  * <Form.RangeInput id="stepRange" max="5" min="0" step="1" />
28
28
  * <div class="d-flex justify-content-between">
29
29
  * <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
30
30
  * </div>
31
- * </Form.Group>
31
+ * </Form.InputGroup>
32
32
  * ```
33
33
  * ### Props
34
34
  * - `class` (string): Optional. Additional CSS classes to apply to the range input.
@@ -5,7 +5,7 @@ Add dialogs to your site for lightboxes, user notifications, or completely custo
5
5
 
6
6
  @example
7
7
  ```svelte
8
- <Modal isShown={true}>
8
+ <Modal.Root isShown={true}>
9
9
  <Modal.Dialog>
10
10
  <Modal.Content>
11
11
  <Modal.Header>
@@ -19,17 +19,17 @@ Add dialogs to your site for lightboxes, user notifications, or completely custo
19
19
  </Modal.Footer>
20
20
  </Modal.Content>
21
21
  </Modal.Dialog>
22
- </Modal>
22
+ </Modal.Root>
23
23
  ```
24
24
 
25
25
  #### Static backdrop
26
26
  ```svelte
27
- <Modal useBackdrop="static">...</Modal>
27
+ <Modal.Root useBackdrop="static">...</Modal.Root>
28
28
  ```
29
29
 
30
30
  #### Keyboard dismissible
31
31
  ```svelte
32
- <Modal isKeyboardDismissible={true}>...</Modal>
32
+ <Modal.Root isKeyboardDismissible={true}>...</Modal.Root>
33
33
  ```
34
34
 
35
35
  ### Props
@@ -5,7 +5,7 @@ import type { Modal } from './index.js';
5
5
  *
6
6
  * @example
7
7
  * ```svelte
8
- * <Modal isShown={true}>
8
+ * <Modal.Root isShown={true}>
9
9
  * <Modal.Dialog>
10
10
  * <Modal.Content>
11
11
  * <Modal.Header>
@@ -19,17 +19,17 @@ import type { Modal } from './index.js';
19
19
  * </Modal.Footer>
20
20
  * </Modal.Content>
21
21
  * </Modal.Dialog>
22
- * </Modal>
22
+ * </Modal.Root>
23
23
  * ```
24
24
  *
25
25
  * #### Static backdrop
26
26
  * ```svelte
27
- * <Modal useBackdrop="static">...</Modal>
27
+ * <Modal.Root useBackdrop="static">...</Modal.Root>
28
28
  * ```
29
29
  *
30
30
  * #### Keyboard dismissible
31
31
  * ```svelte
32
- * <Modal isKeyboardDismissible={true}>...</Modal>
32
+ * <Modal.Root isKeyboardDismissible={true}>...</Modal.Root>
33
33
  * ```
34
34
  *
35
35
  * ### Props
@@ -5,37 +5,37 @@ Build hidden sidebars into your project for navigation, shopping carts, and more
5
5
 
6
6
  @example
7
7
  ```svelte
8
- <Offcanvas placement="start" isVisible={true}>
8
+ <Offcanvas.Root placement="start" isShown={true}>
9
9
  <Offcanvas.Header>
10
10
  <Offcanvas.Title>Offcanvas Title</Offcanvas.Title>
11
11
  </Offcanvas.Header>
12
12
  <Offcanvas.Body>
13
13
  Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
14
14
  </Offcanvas.Body>
15
- </Offcanvas>
15
+ </Offcanvas.Root>
16
16
  ```
17
17
 
18
18
  #### Placement options
19
19
  ```svelte
20
- <Offcanvas placement="start">...</Offcanvas>
21
- <Offcanvas placement="end">...</Offcanvas>
22
- <Offcanvas placement="top">...</Offcanvas>
23
- <Offcanvas placement="bottom">...</Offcanvas>
20
+ <Offcanvas.Root placement="start">...</Offcanvas.Root>
21
+ <Offcanvas.Root placement="end">...</Offcanvas.Root>
22
+ <Offcanvas.Root placement="top">...</Offcanvas.Root>
23
+ <Offcanvas.Root placement="bottom">...</Offcanvas.Root>
24
24
  ```
25
25
 
26
26
  #### Body scrolling
27
27
  ```svelte
28
- <Offcanvas bodyScrolling={true}>...</Offcanvas>
28
+ <Offcanvas.Root isBodyScrollable={true}>...</Offcanvas.Root>
29
29
  ```
30
30
 
31
31
  #### Static backdrop
32
32
  ```svelte
33
- <Offcanvas isStatic={true}>...</Offcanvas>
33
+ <Offcanvas.Root useBackdrop="static">...</Offcanvas.Root>
34
34
  ```
35
35
 
36
36
  #### Responsive offcanvas
37
37
  ```svelte
38
- <Offcanvas breakpoint="lg">...</Offcanvas>
38
+ <Offcanvas.Root showOnBreakpoint="lg">...</Offcanvas.Root>
39
39
  ```
40
40
 
41
41
  ### Props
@@ -5,37 +5,37 @@ import type { Offcanvas } from './index.js';
5
5
  *
6
6
  * @example
7
7
  * ```svelte
8
- * <Offcanvas placement="start" isVisible={true}>
8
+ * <Offcanvas.Root placement="start" isShown={true}>
9
9
  * <Offcanvas.Header>
10
10
  * <Offcanvas.Title>Offcanvas Title</Offcanvas.Title>
11
11
  * </Offcanvas.Header>
12
12
  * <Offcanvas.Body>
13
13
  * Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
14
14
  * </Offcanvas.Body>
15
- * </Offcanvas>
15
+ * </Offcanvas.Root>
16
16
  * ```
17
17
  *
18
18
  * #### Placement options
19
19
  * ```svelte
20
- * <Offcanvas placement="start">...</Offcanvas>
21
- * <Offcanvas placement="end">...</Offcanvas>
22
- * <Offcanvas placement="top">...</Offcanvas>
23
- * <Offcanvas placement="bottom">...</Offcanvas>
20
+ * <Offcanvas.Root placement="start">...</Offcanvas.Root>
21
+ * <Offcanvas.Root placement="end">...</Offcanvas.Root>
22
+ * <Offcanvas.Root placement="top">...</Offcanvas.Root>
23
+ * <Offcanvas.Root placement="bottom">...</Offcanvas.Root>
24
24
  * ```
25
25
  *
26
26
  * #### Body scrolling
27
27
  * ```svelte
28
- * <Offcanvas bodyScrolling={true}>...</Offcanvas>
28
+ * <Offcanvas.Root isBodyScrollable={true}>...</Offcanvas.Root>
29
29
  * ```
30
30
  *
31
31
  * #### Static backdrop
32
32
  * ```svelte
33
- * <Offcanvas isStatic={true}>...</Offcanvas>
33
+ * <Offcanvas.Root useBackdrop="static">...</Offcanvas.Root>
34
34
  * ```
35
35
  *
36
36
  * #### Responsive offcanvas
37
37
  * ```svelte
38
- * <Offcanvas breakpoint="lg">...</Offcanvas>
38
+ * <Offcanvas.Root showOnBreakpoint="lg">...</Offcanvas.Root>
39
39
  * ```
40
40
  *
41
41
  * ### Props
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "author": "Wink, Inc.",
3
3
  "name": "@winkintel/bootstrap-svelte",
4
- "version": "1.0.7",
4
+ "version": "1.0.10",
5
5
  "description": "Bootstrap components for Svelte 5 with TypeScript support.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/WinkIntel/bootstrap-svelte.git"
10
10
  },
11
- "homepage": "https://github.com/WinkIntel/bootstrap-svelte#readme",
11
+ "homepage": "https://bootstrap-svelte.vercel.app/",
12
12
  "bugs": {
13
13
  "url": "https://github.com/WinkIntel/bootstrap-svelte/issues"
14
14
  },
@@ -99,10 +99,15 @@
99
99
  },
100
100
  "keywords": [
101
101
  "bootstrap",
102
+ "bootstrap5",
103
+ "bootstrap-5",
102
104
  "components",
105
+ "component-library",
103
106
  "svelte",
104
107
  "svelte5",
108
+ "sveltekit",
105
109
  "typescript",
106
- "ui"
110
+ "ui",
111
+ "ui-library"
107
112
  ]
108
113
  }