@asd20/ui-next 2.0.0 → 2.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.0...ui-next-v2.0.1) (2026-03-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * harden vue 3 navigation focus refs ([ba0bf4f](https://github.com/academydistrict20/asd20-ui-next/commit/ba0bf4f3b67661b2a837a6257ded847d8a0aabe8))
9
+
3
10
  # [2.0.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v1.0.11...ui-next-v2.0.0) (2026-03-27)
4
11
 
5
12
 
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @asd20/ui-next
2
2
 
3
- Vue component library migration workspace for ASD20.
3
+ Vue 3 component library for ASD20 shared UI surfaces.
4
+
5
+ The current published baseline is `@asd20/ui-next@2.0.0`. This release is Vue 3-only and ships the model-only shared input contract.
4
6
 
5
7
  ## Public Entry Points
6
8
 
@@ -22,7 +24,7 @@ npm run storybook
22
24
  npm run build
23
25
  ```
24
26
 
25
- ## Package Artifact
27
+ ## Release Validation
26
28
 
27
29
  Build the staged publish artifact with:
28
30
 
@@ -30,28 +32,22 @@ Build the staged publish artifact with:
30
32
  npm run build:package
31
33
  ```
32
34
 
33
- This writes a curated source-based package to `dist/package` so release and pack validation do not publish Storybook files, snapshot tests, or the local app shell.
34
-
35
- The staged package also trims undocumented heavyweight `public/` media. Only explicit runtime public assets still referenced by package source are copied into `dist/package/public`.
36
-
37
- The staged package also trims `src/data` down to the small runtime subset still used by exported source. Story/demo payloads remain in the repo but are not staged for publish.
38
-
39
- Verify the publish path end to end with:
35
+ Validate the publish shape end to end with:
40
36
 
41
37
  ```bash
42
38
  npm run verify:publish
43
39
  ```
44
40
 
45
- That command rebuilds `dist/package`, verifies the root and staged export contract, and runs `npm pack --dry-run` against the staged package with a temporary writable npm cache.
46
-
47
- It also validates the checked public API contract for package subpaths and public entrypoint named exports, so export-surface drift fails before release.
41
+ That flow rebuilds `dist/package`, verifies the root and staged export contract, checks the public API surface, and runs `npm pack --dry-run` against the staged package.
48
42
 
49
- Verify the release path against a throwaway packed consumer app with:
43
+ Validate the packed consumer install path with:
50
44
 
51
45
  ```bash
52
46
  npm run verify:release
53
47
  ```
54
48
 
55
- That command runs the publish verifier, packs the staged package into a tarball, installs that tarball into a temporary Vue 3 smoke app, and confirms the consumer build succeeds against the installed package shape.
49
+ That flow packs the staged package into a tarball, installs it into a temporary Vue 3 smoke app, and confirms the consumer build succeeds against the installed package shape.
50
+
51
+ ## Migration Record
56
52
 
57
- The smoke app also compiles `v-model` usage against the exported input primitives, so Vue 3 two-way-binding regressions are part of the release check.
53
+ The package is now release-ready and published, but the migration record is still kept under `docs/migration/` for downstream audit history, release decisions, and future cleanup planning.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -108,11 +108,16 @@ export default {
108
108
  this.$emit('update:open', value)
109
109
  this.$emit('update:modelValue', value)
110
110
  },
111
+ focusRef(refName) {
112
+ const ref = this.$refs[refName]
113
+ const focusTarget = ref?.$el || ref
114
+ if (typeof focusTarget?.focus === 'function') {
115
+ focusTarget.focus()
116
+ }
117
+ },
111
118
  setFocus() {
112
119
  this.$nextTick(() => {
113
- if (this.$refs.closeButton && this.$refs.closeButton.$el) {
114
- this.$refs.closeButton.$el.focus()
115
- }
120
+ this.focusRef('closeButton')
116
121
  })
117
122
  },
118
123
  },
@@ -67,19 +67,26 @@ export default {
67
67
  menuActive: function(val) {
68
68
  if (!val) {
69
69
  this.$nextTick(() => {
70
- this.$refs.menuButton.$el.focus()
70
+ this.focusRef('menuButton')
71
71
  })
72
72
  }
73
73
  },
74
74
  searchActive: function(val) {
75
75
  if (!val) {
76
76
  this.$nextTick(() => {
77
- this.$refs.searchButton.$el.focus()
77
+ this.focusRef('searchButton')
78
78
  })
79
79
  }
80
80
  },
81
81
  },
82
82
  methods: {
83
+ focusRef(refName) {
84
+ const ref = this.$refs[refName]
85
+ const focusTarget = ref?.$el || ref
86
+ if (typeof focusTarget?.focus === 'function') {
87
+ focusTarget.focus()
88
+ }
89
+ },
83
90
  toggleMenu(event) {
84
91
  this.$emit('update:menuActive', !this.menuActive)
85
92
  this.$emit('keyboardTriggeredLastAction', event.type === 'keyup')
@@ -123,7 +123,7 @@ export default {
123
123
  menuOpen: function (val) {
124
124
  this.$nextTick(() => {
125
125
  if (val) {
126
- this.$refs.siteMenu.$el.focus()
126
+ this.focusSiteMenu()
127
127
  }
128
128
  })
129
129
  },
@@ -139,6 +139,16 @@ export default {
139
139
  window.removeEventListener('resize', this.handleResize)
140
140
  },
141
141
  methods: {
142
+ focusSiteMenu() {
143
+ const focusTarget =
144
+ this.$refs.siteMenu?.$refs?.menuContainer ||
145
+ this.$refs.siteMenu?.$el ||
146
+ this.$refs.siteMenu
147
+
148
+ if (typeof focusTarget?.focus === 'function') {
149
+ focusTarget.focus()
150
+ }
151
+ },
142
152
  onKeyboardToggleEvent(event) {
143
153
  this.keyboardToggleEvent = event
144
154
  },
@@ -1962,17 +1962,19 @@ export default {
1962
1962
  },
1963
1963
 
1964
1964
  focusQuery() {
1965
- if (this.$refs.query && this.$refs.query.$el) {
1966
- const input = this.$refs.query.$el.querySelector('input')
1967
- if (input) input.focus()
1968
- }
1965
+ const input = this.getQueryInput()
1966
+ if (input) input.focus()
1969
1967
  },
1970
1968
 
1971
1969
  blurQuery() {
1972
- if (this.$refs.query && this.$refs.query.$el) {
1973
- const input = this.$refs.query.$el.querySelector('input')
1974
- if (input) input.blur()
1975
- }
1970
+ const input = this.getQueryInput()
1971
+ if (input) input.blur()
1972
+ },
1973
+
1974
+ getQueryInput() {
1975
+ const queryRef = this.$refs.query?.$el || this.$refs.query
1976
+ if (typeof queryRef?.querySelector !== 'function') return null
1977
+ return queryRef.querySelector('input')
1976
1978
  },
1977
1979
 
1978
1980
  getResultsViewportRef(tabLabel = this.currentTab) {