svelora 2.1.0 → 2.1.1

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
@@ -125,10 +125,53 @@ defineConfig({
125
125
 
126
126
  ## Publish
127
127
 
128
+ Release checklist: [RELEASE_CHECKLIST.md](./RELEASE_CHECKLIST.md)
129
+
128
130
  ```bash
129
131
  bun run release:verify
130
132
  ```
131
133
 
134
+ One command release:
135
+
136
+ ```bash
137
+ bun run release:patch
138
+ ```
139
+
140
+ The release command generates `CHANGELOG.md` automatically from unreleased git commits.
141
+ It groups commit messages into `Added`, `Changed`, and `Fixed`, writes the next version section, and resets `## [Unreleased]` back to the template automatically.
142
+ If you still have local changes that are not committed yet, pass a work commit message and the script will create that commit before publishing.
143
+
144
+ Refresh the template manually if needed:
145
+
146
+ ```bash
147
+ bun run changelog:template
148
+ ```
149
+
150
+ Release with a work commit message for uncommitted changes:
151
+
152
+ ```bash
153
+ bun run release:patch -- "feat(button): improve loading state"
154
+ ```
155
+
156
+ Other version bumps:
157
+
158
+ ```bash
159
+ bun run release:minor
160
+ # bun run release:major
161
+ ```
162
+
163
+ Full verification before publish:
164
+
165
+ ```bash
166
+ bun run release:patch:full
167
+ ```
168
+
169
+ Dry run:
170
+
171
+ ```bash
172
+ bun run release:patch:dry
173
+ ```
174
+
132
175
  ```bash
133
176
  npm login
134
177
  npm publish --access public
@@ -1,6 +1,9 @@
1
1
  <script lang="ts" module>
2
2
  import type { LinkProps } from './link.types.js'
3
3
 
4
+ const navigationEvent = 'svelora:navigation'
5
+ let isHistoryPatched = false
6
+
4
7
  export type Props = LinkProps
5
8
 
6
9
  function parseUrl(url: string, baseUrl: URL) {
@@ -47,11 +50,64 @@
47
50
 
48
51
  return link === '/' ? current === '/' : current === link || current.startsWith(`${link}/`)
49
52
  }
53
+
54
+ function dispatchNavigationEvent() {
55
+ if (typeof window === 'undefined') {
56
+ return
57
+ }
58
+
59
+ window.dispatchEvent(new Event(navigationEvent))
60
+ }
61
+
62
+ function patchHistoryMethod(method: 'pushState' | 'replaceState') {
63
+ const historyMethod = window.history[method].bind(window.history) as (
64
+ ...args: Parameters<History['pushState']>
65
+ ) => void
66
+
67
+ Object.defineProperty(window.history, method, {
68
+ configurable: true,
69
+ value: (...args: Parameters<History['pushState']>) => {
70
+ historyMethod(...args)
71
+ dispatchNavigationEvent()
72
+ }
73
+ })
74
+ }
75
+
76
+ function ensureNavigationEvents() {
77
+ if (typeof window === 'undefined' || isHistoryPatched) {
78
+ return
79
+ }
80
+
81
+ isHistoryPatched = true
82
+ patchHistoryMethod('pushState')
83
+ patchHistoryMethod('replaceState')
84
+ }
85
+
86
+ function subscribeToLocation(callback: () => void) {
87
+ if (typeof window === 'undefined') {
88
+ return () => undefined
89
+ }
90
+
91
+ ensureNavigationEvents()
92
+
93
+ const handleLocationChange = () => callback()
94
+
95
+ handleLocationChange()
96
+ window.addEventListener('popstate', handleLocationChange)
97
+ window.addEventListener('hashchange', handleLocationChange)
98
+ window.addEventListener(navigationEvent, handleLocationChange)
99
+
100
+ return () => {
101
+ window.removeEventListener('popstate', handleLocationChange)
102
+ window.removeEventListener('hashchange', handleLocationChange)
103
+ window.removeEventListener(navigationEvent, handleLocationChange)
104
+ }
105
+ }
50
106
  </script>
51
107
 
52
108
  <script lang="ts">
109
+ import { onMount } from 'svelte'
53
110
  import { twMerge } from 'tailwind-merge'
54
- import { page } from '$app/state'
55
111
  import { getComponentConfig } from '../config.js'
56
112
  import { linkDefaults, linkVariants } from './link.variants.js'
57
113
 
@@ -80,6 +136,13 @@
80
136
  }: Props = $props()
81
137
 
82
138
  const isLink = $derived(!!href)
139
+ let currentUrl = $state<URL | undefined>(undefined)
140
+
141
+ onMount(() => {
142
+ return subscribeToLocation(() => {
143
+ currentUrl = new URL(window.location.href)
144
+ })
145
+ })
83
146
 
84
147
  const isExternal = $derived(
85
148
  isLink &&
@@ -102,14 +165,14 @@
102
165
 
103
166
  const isActive = $derived.by(() => {
104
167
  if (active !== undefined) return active
105
- if (!isLink || !page.url || isExternal) return false
168
+ if (!isLink || !currentUrl || isExternal) return false
106
169
 
107
- const link = parseUrl(href!, page.url)
170
+ const link = parseUrl(href!, currentUrl)
108
171
 
109
- if (exactHash && link.hash !== page.url.hash) return false
110
- if (!isQueryMatch(link.query, page.url.searchParams, exactQuery)) return false
172
+ if (exactHash && link.hash !== currentUrl.hash) return false
173
+ if (!isQueryMatch(link.query, currentUrl.searchParams, exactQuery)) return false
111
174
 
112
- return isPathnameMatch(link.pathname, page.url.pathname, exact)
175
+ return isPathnameMatch(link.pathname, currentUrl.pathname, exact)
113
176
  })
114
177
 
115
178
  const baseClass = $derived.by(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelora",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Modern primitive-based UI component library for Svelte 5",
5
5
  "author": "asphum",
6
6
  "license": "MIT",
@@ -28,8 +28,17 @@
28
28
  "lint:fix": "biome check --write .",
29
29
  "test:unit": "vitest",
30
30
  "test": "bun run test:unit -- --run",
31
+ "changelog:template": "node ./scripts/changelog-template.mjs",
31
32
  "release:verify": "bun run check && bun run prepack && npm pack --dry-run",
32
33
  "release:verify:full": "bun run check && bun run test && bun run prepack && npm pack --dry-run",
34
+ "release": "node ./scripts/release.mjs",
35
+ "release:patch": "node ./scripts/release.mjs patch",
36
+ "release:minor": "node ./scripts/release.mjs minor",
37
+ "release:major": "node ./scripts/release.mjs major",
38
+ "release:patch:full": "node ./scripts/release.mjs patch --full",
39
+ "release:minor:full": "node ./scripts/release.mjs minor --full",
40
+ "release:major:full": "node ./scripts/release.mjs major --full",
41
+ "release:patch:dry": "node ./scripts/release.mjs patch --dry-run",
33
42
  "clean": "rm -rf dist node_modules build .svelte-kit"
34
43
  },
35
44
  "files": [