-
Notifications
You must be signed in to change notification settings - Fork 333
feat(select-wrapper,base-select,tree-select,grid-select):tree-select support lazy loading #3915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis PR introduces lazy loading support for TinyTreeSelect, migrates select-wrapper demos to use TinySelectWrapper, and updates base-select's dropdown visibility logic to handle panel slots. Changes span new component props, demo examples, API documentation, and selector updates across multiple demo files. Changes
Sequence DiagramsequenceDiagram
actor User
participant TreeSelect as TinyTreeSelect<br/>(Component)
participant TreeNode as Tree Node
participant AsyncLoad as Load Handler
participant Data as Data Source
User->>TreeSelect: Click node (lazy=true)
TreeSelect->>TreeSelect: Check node.level
alt Initial Load (level === 0)
TreeSelect->>AsyncLoad: load(node, resolve)
AsyncLoad->>Data: Fetch top-level nodes
Data-->>AsyncLoad: [node1, node2, node3]
AsyncLoad->>TreeSelect: resolve(topNodes)
else Subsequent Load (has children)
TreeSelect->>AsyncLoad: load(node, resolve)
AsyncLoad->>AsyncLoad: setTimeout()
AsyncLoad->>Data: Generate child nodes<br/>from parent
Data-->>AsyncLoad: [child1...child5]
AsyncLoad->>TreeSelect: resolve(childNodes)
end
TreeSelect->>TreeNode: Render loaded nodes
TreeSelect->>TreeSelect: afterLoad(data)
TreeSelect-->>User: Display expanded tree
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
♻️ Duplicate comments (3)
examples/sites/demos/pc/app/select-wrapper/filter-method.vue (1)
39-39: Wrapper migration - see verification request in disabled.vue.This file follows the same
TinySelectWrapperaliasing pattern. Refer to the verification request in the disabled.vue review.examples/sites/demos/pc/app/select-wrapper/nest-tree.vue (1)
67-67: Wrapper migration - see verification request in disabled.vue.This file follows the same
TinySelectWrapperaliasing pattern. Refer to the verification request in the disabled.vue review.examples/sites/demos/pc/app/select-wrapper/allow-create.vue (1)
54-61: Wrapper migration - see verification request in disabled.vue.This file follows the same
TinySelectWrapperaliasing pattern. Refer to the verification request in the disabled.vue review.
🧹 Nitpick comments (8)
examples/sites/demos/pc/app/select-wrapper/filter-method.spec.ts (1)
3-89: Consider extracting shared test logic to reduce duplication.The two test cases share nearly identical filtering logic. Consider extracting the common test steps into a helper function to improve maintainability.
Example refactor
async function testFilteringBehavior(page, selectIndex: 'first' | number) { const wrap = page.locator('#filter-method') const select = typeof selectIndex === 'number' ? wrap.locator('.tiny-select').nth(selectIndex) : wrap.locator('.tiny-select').first() const input = select.locator('.tiny-input__inner') const dropdown = page.locator('body > .tiny-select-dropdown') const option = dropdown.locator('.tiny-option') // Test no match case await input.click() await expect(page.getByText('No Match')).toBeHidden() await input.press('1') await expect(input).toHaveValue('1') await input.press('Enter') await expect(page.getByText('No Match')).toBeVisible() await page.waitForTimeout(500) let allListItems = await option.all() allListItems.forEach(async (item) => { await expect(item).toHaveCSS('display', 'none') }) // Test successful filter await input.fill('上海') await expect(input).toHaveValue('上海') await input.press('Enter') await page.waitForTimeout(200) allListItems.forEach(async (item) => { const isVisibleItem = (await item.innerText()) === '上海' if (isVisibleItem) { await expect(item).toHaveCSS('display', 'flex') } else { await expect(item).toHaveCSS('display', 'none') } }) await expect(option.filter({ hasText: '上海' })).toBeVisible() await option.filter({ hasText: '上海' }).click() await expect(input).toHaveValue('上海') } test('默认搜索', async ({ page }) => { page.on('pageerror', (exception) => expect(exception).toBeNull()) await page.goto('select-wrapper#filter-method') await testFilteringBehavior(page, 'first') }) test('自定义过滤', async ({ page }) => { page.on('pageerror', (exception) => expect(exception).toBeNull()) await page.goto('select-wrapper#filter-method') await testFilteringBehavior(page, 1) })examples/sites/demos/pc/app/select-wrapper/events.spec.ts (1)
68-68: Refactor to use semantic locators instead of fragile CSS path.The deep CSS selector
.is-show-close > div > .tiny-input__suffix > .tiny-input__suffix-inner > svgis brittle and will break with minor DOM structure changes. This approach is inconsistent with line 29, which correctly uses semantic locators (getByLabel+getByRole).Consider refactoring to match the pattern used on line 29, or use a more resilient selector like
getByRole('button', { name: /clear/i })or a test-id attribute.🔎 Suggested approach using semantic locators:
- await page.locator('.is-show-close > div > .tiny-input__suffix > .tiny-input__suffix-inner > svg').first().click() + await select.getByRole('img', { name: /clear|close/i }).click()Or, if the structure matches line 29:
- await page.locator('.is-show-close > div > .tiny-input__suffix > .tiny-input__suffix-inner > svg').first().click() + await page.getByLabel('示例', { exact: true }).getByRole('img').nth(1).click()examples/sites/demos/pc/app/select-wrapper/cache-usage.spec.ts (1)
13-17: Consider the selector change from semantic to CSS class-based.The selectors changed from
getByRole('listitem')to.tiny-option. While this change may be necessary due to the component structure, CSS class-based selectors are more brittle than semantic ARIA-based selectors. If the component's DOM structure or class names change, these tests will break.If the
TinySelectWrapperimplementation still exposes proper ARIA roles, consider reverting to semantic selectors for better test resilience:- await dropdown.locator('.tiny-option').filter({ hasText: '北京' }).click() + await dropdown.getByRole('listitem').filter({ hasText: '北京' }).click()However, if the component structure genuinely changed and no longer uses list items, the current approach is acceptable.
examples/sites/demos/pc/app/tree-select/lazy-composition-api.vue (1)
13-39: LGTM! Well-structured lazy loading demonstration.The load function correctly demonstrates async lazy loading with:
- Initial load detection via
node.level === 0- Subsequent loads via
node.datapresence- Async simulation with
setTimeout- Dynamic node properties (disabled, isLeaf)
💡 Optional: Consider clearer random boolean generation
The expression
Math.random() - 0.5 > 0works correctly but could be more readable:- disabled: Math.random() - 0.5 > 0, // 随机禁用节点 - isLeaf: Math.random() - 0.5 > 0 // 随机设置叶子节点 + disabled: Math.random() > 0.5, // 随机禁用节点 + isLeaf: Math.random() > 0.5 // 随机设置叶子节点Both produce 50% probability, but
Math.random() > 0.5is more straightforward.examples/sites/demos/pc/app/select-wrapper/allow-create.spec.ts (1)
19-19: Consider accessibility implications of selector change.The test now uses CSS class selectors (
.tiny-option) instead of ARIA role selectors (getByRole('listitem')). While this aligns with the wrapper's DOM structure, it reduces verification of accessible markup.Consider adding explicit accessibility checks:
If the wrapper's option elements should maintain ARIA roles, consider adding a separate test to verify the proper ARIA markup:
// Verify options have proper ARIA roles await expect(dropdown.locator('[role="option"]').first()).toBeVisible()Alternatively, if
.tiny-optionelements intentionally don't use ARIA roles, document this architectural decision.Also applies to: 24-24, 49-49
examples/sites/demos/pc/app/tree-select/lazy.vue (1)
24-30: Consider async initial load for demo consistency.The initial load (level 0) resolves synchronously, while subsequent loads (lines 43-44) use
setTimeout. This inconsistency may confuse users trying to understand the lazy loading pattern. Consider wrapping the initial resolve insetTimeoutas well for a consistent demo experience.🔎 Suggested change for consistency:
if (node.level === 0) { - resolve([ - { value: '1', label: '一级 1' }, - { value: '2', label: '一级 2' }, - { value: '3', label: '一级 3' } - ]) + setTimeout(() => { + resolve([ + { value: '1', label: '一级 1' }, + { value: '2', label: '一级 2' }, + { value: '3', label: '一级 3' } + ]) + }, 500) }examples/sites/demos/apis/tree-select.js (2)
280-305: Type consistency betweenloadandafter-load.The
loadprop uses inline function signature'(node, resolve) => void'(line 282), whileafter-loaduses generic'Function'(line 296). Consider using consistent typing approach for both, preferably the more descriptive function signature forafter-loadas well (e.g.,'(data: any) => void').
322-324: Define referenced typesITreeNodeVmandIResolveType.The interface references
ITreeNodeVmandIResolveTypebut these types are not defined in thetypessection. Users consulting the API docs won't know what these types represent.🔎 Add missing type definitions:
interface ITreeOption { data: ITreeNode[] // 树数据,用法同 Tree lazy?: boolean // 是否懒加载子节点 - load?: (node: ITreeNodeVm, resolve: IResolveType) => void // 加载子树数据的方法 + load?: (node: ITreeNodeVm, resolve: (data: ITreeNode[]) => void) => void // 加载子树数据的方法 afterLoad?: (data: any) => void // 节点懒加载完成后的回调函数 } + +interface ITreeNodeVm { + level: number // 节点层级 + data: ITreeNode // 节点数据 +}
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (102)
examples/sites/demos/apis/tree-select.js(2 hunks)examples/sites/demos/mobile-first/app/tree-select/lazy.vue(1 hunks)examples/sites/demos/mobile-first/app/tree-select/webdoc/tree-select.js(1 hunks)examples/sites/demos/pc/app/select-wrapper/all-text.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/all-text.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/allow-create.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/allow-create.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/automatic-dropdown.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/automatic-dropdown.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/basic-usage.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/basic-usage.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/binding-obj.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/binding-obj.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/cache-usage.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/cache-usage.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/clear-no-match-value.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/clear-no-match-value.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/clearable.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/clearable.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/collapse-tags.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/collapse-tags.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/copy-multi.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/copy-multi.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/copy-single.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/copy-single.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/disabled.spec.ts(4 hunks)examples/sites/demos/pc/app/select-wrapper/disabled.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/events.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/events.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/extra-query-params.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/filter-method.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/filter-method.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/filter-mode.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/hide-drop.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/hide-drop.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/init-label.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/input-box-type.spec.ts(4 hunks)examples/sites/demos/pc/app/select-wrapper/input-box-type.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/is-drop-inherit-width.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/is-drop-inherit-width.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/manual-focus-blur.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/manual-focus-blur.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/map-field.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/map-field.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/memoize-usage.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/memoize-usage.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/multiple-mix.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/multiple.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/multiple.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/native-properties.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/native-properties.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid-disable.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid-disable.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid-init-query.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid-remote.spec.ts(5 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid-remote.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/nest-grid.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-radio-grid-much-data.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-radio-grid-much-data.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/nest-tree.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/nest-tree.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/no-data-text.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/no-data-text.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/optimization.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/option-group.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/option-group.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/popup-style-position.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/popup-style-position.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/remote-method.spec.ts(3 hunks)examples/sites/demos/pc/app/select-wrapper/remote-method.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/searchable.spec.ts(2 hunks)examples/sites/demos/pc/app/select-wrapper/searchable.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/show-alloption.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/show-alloption.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/show-tip.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/size.spec.ts(4 hunks)examples/sites/demos/pc/app/select-wrapper/size.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-default.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-default.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-empty.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-empty.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-header-footer.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-header-footer.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-label.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-prefix.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-prefix.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-reference.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/slot-reference.vue(1 hunks)examples/sites/demos/pc/app/select-wrapper/tag-type.spec.ts(1 hunks)examples/sites/demos/pc/app/select-wrapper/tag-type.vue(1 hunks)examples/sites/demos/pc/app/tree-select/lazy-composition-api.vue(1 hunks)examples/sites/demos/pc/app/tree-select/lazy-multiple-composition-api.vue(1 hunks)examples/sites/demos/pc/app/tree-select/lazy-multiple.vue(1 hunks)examples/sites/demos/pc/app/tree-select/lazy.vue(1 hunks)examples/sites/demos/pc/app/tree-select/webdoc/tree-select.js(1 hunks)packages/renderless/src/base-select/index.ts(1 hunks)packages/vue/src/base-select/src/mobile-first.vue(1 hunks)packages/vue/src/base-select/src/pc.vue(1 hunks)packages/vue/src/tree-select/src/index.ts(1 hunks)packages/vue/src/tree-select/src/mobile-first.vue(2 hunks)packages/vue/src/tree-select/src/pc.vue(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-25T03:43:05.285Z
Learnt from: Davont
Repo: opentiny/tiny-vue PR: 2513
File: packages/vue/src/huicharts/huicharts-histogram/src/chart-histogram.vue:33-36
Timestamp: 2024-11-25T03:43:05.285Z
Learning: 在 Tiny Vue 代码库中,使用 `chart-core` 中的 `huiChartOption` 的组件,不应在其 `data` 中定义 `huiChartOption` 或 `option`,而是应该依赖 `chart-core` 提供的 `huiChartOption`。
Applied to files:
examples/sites/demos/pc/app/select-wrapper/slot-label.vueexamples/sites/demos/pc/app/select-wrapper/slot-header-footer.vueexamples/sites/demos/pc/app/select-wrapper/popup-style-position.vueexamples/sites/demos/pc/app/select-wrapper/automatic-dropdown.vueexamples/sites/demos/pc/app/select-wrapper/slot-reference.vueexamples/sites/demos/pc/app/select-wrapper/collapse-tags.vueexamples/sites/demos/pc/app/select-wrapper/remote-method.vueexamples/sites/demos/pc/app/select-wrapper/allow-create.vueexamples/sites/demos/pc/app/select-wrapper/events.vueexamples/sites/demos/pc/app/select-wrapper/option-group.vueexamples/sites/demos/pc/app/select-wrapper/clear-no-match-value.vueexamples/sites/demos/pc/app/select-wrapper/filter-method.vueexamples/sites/demos/pc/app/select-wrapper/show-alloption.vueexamples/sites/demos/pc/app/select-wrapper/binding-obj.vueexamples/sites/demos/pc/app/select-wrapper/hide-drop.vueexamples/sites/demos/pc/app/select-wrapper/disabled.vueexamples/sites/demos/pc/app/select-wrapper/show-tip.vueexamples/sites/demos/pc/app/select-wrapper/slot-prefix.vueexamples/sites/demos/pc/app/select-wrapper/copy-multi.vueexamples/sites/demos/pc/app/select-wrapper/memoize-usage.vueexamples/sites/demos/pc/app/select-wrapper/copy-single.vueexamples/sites/demos/pc/app/select-wrapper/clearable.vueexamples/sites/demos/pc/app/select-wrapper/slot-default.vueexamples/sites/demos/pc/app/select-wrapper/basic-usage.vueexamples/sites/demos/pc/app/select-wrapper/is-drop-inherit-width.vueexamples/sites/demos/pc/app/select-wrapper/filter-mode.vueexamples/sites/demos/pc/app/select-wrapper/manual-focus-blur.vueexamples/sites/demos/pc/app/select-wrapper/all-text.vueexamples/sites/demos/pc/app/select-wrapper/input-box-type.vueexamples/sites/demos/pc/app/select-wrapper/multiple.vueexamples/sites/demos/pc/app/select-wrapper/searchable.vueexamples/sites/demos/pc/app/select-wrapper/no-data-text.vueexamples/sites/demos/pc/app/select-wrapper/native-properties.vueexamples/sites/demos/pc/app/select-wrapper/tag-type.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (100)
examples/sites/demos/pc/app/select-wrapper/manual-focus-blur.spec.ts (1)
5-5: LGTM! Verify test passes with the new component.The navigation path update from
select#manual-focus-blurtoselect-wrapper#manual-focus-blurcorrectly aligns with the migration to TinySelectWrapper. The change is consistent with the broader migration pattern across multiple test specs.Please ensure this test passes with the new select-wrapper component, particularly verifying that the dropdown selector
.tiny-select-dropdownon line 7 still correctly targets the rendered dropdown.examples/sites/demos/pc/app/select-wrapper/hide-drop.spec.ts (1)
5-5: LGTM! Route update aligns with component migration.The navigation path update from
select#hide-droptoselect-wrapper#hide-dropcorrectly reflects the broader migration of select demos to use the select-wrapper component structure. The test logic and assertions remain unchanged and appropriate for verifying the hide-drop functionality.examples/sites/demos/pc/app/select-wrapper/no-data-text.vue (1)
24-24: LGTM! Import alias correctly migrates to TinySelectWrapper.The import change aliases
TinySelectWrapperasTinySelect, allowing the template and component registration to remain unchanged. This is consistent with the PR-wide migration pattern.examples/sites/demos/pc/app/select-wrapper/no-data-text.spec.ts (1)
5-5: LGTM! Navigation paths correctly updated.All three test cases now navigate to
select-wrapper#no-data-text, correctly reflecting the demo's new location. The test logic, selectors, and assertions remain unchanged and appropriate.Also applies to: 18-18, 31-31
examples/sites/demos/pc/app/select-wrapper/searchable.spec.ts (1)
5-5: LGTM! Navigation targets correctly updated for select-wrapper migration.The changes appropriately update the test navigation URLs from
select#searchabletoselect-wrapper#searchable, aligning with the PR's objective to migrate demos to use TinySelectWrapper. The test logic remains unchanged, which is correct since the component interface is preserved.Also applies to: 37-37
examples/sites/demos/pc/app/select-wrapper/map-field.spec.ts (1)
5-5: LGTM! Navigation paths updated consistently.The test navigation paths have been correctly updated to target
select-wrapper#map-fieldinstead ofselect#map-field, aligning with the component migration from TinySelect to TinySelectWrapper.Also applies to: 25-25
examples/sites/demos/pc/app/select-wrapper/map-field.vue (2)
21-21: LGTM! Import alias maintains API compatibility.The import has been correctly updated to use TinySelectWrapper aliased as TinySelect, which maintains backward compatibility with the existing template and component registration. This is consistent with the broader demo migration pattern.
1-68: Note: These files don't appear to relate to the PR's stated objective.The PR title indicates "tree-select support lazy loading", but these files (map-field.vue and map-field.spec.ts) contain standard select component demos with no tree-select or lazy loading functionality. These changes appear to be part of a broader demo migration from TinySelect to TinySelectWrapper rather than the core feature implementation mentioned in the PR objectives.
examples/sites/demos/pc/app/select-wrapper/clear-no-match-value.vue (1)
23-23: Verify that TinySelectWrapper supports theclear-no-match-valueprop.The demo tests the
clear-no-match-valuefeature (lines 7 and 16), which must be fully supported byTinySelectWrapperfor this example to work correctly. Ensure the component implementation includes this prop and maintains identical behavior to the originalTinySelect.examples/sites/demos/pc/app/select-wrapper/binding-obj.vue (1)
14-14: Verify TinySelectWrapper API compatibility with demo features.This demo migrates from
TinySelecttoTinySelectWrapper. EnsureTinySelectWrapperfully supports:value-keyprop for object value identification,v-modelbinding with object values, and the default slot pattern with<tiny-option>components.examples/sites/demos/pc/app/select-wrapper/slot-header-footer.spec.ts (1)
5-5: URL correctly updated for component migration.The navigation URL has been properly updated from
selecttoselect-wrapperon line 5. The corresponding demo component exists with matching selectors (.select-header, .select-footer) and expected text content.examples/sites/demos/pc/app/select-wrapper/searchable.vue (1)
26-26: Clean migration to TinySelectWrapper.The aliasing approach is clean and requires no changes to the component registration or template. TinySelectWrapper fully supports all props used in this demo:
searchable,multiple, andreserve-keyword. This aligns with the PR's objective to migrate select-wrapper demos to use TinySelectWrapper.examples/sites/demos/pc/app/select-wrapper/nest-radio-grid-much-data.spec.ts (1)
5-5: LGTM! Selector updates align with the select-wrapper migration.The navigation target and caret selector have been correctly updated to reflect the migration from
selecttoselect-wrapperand the internal use ofbase-selectcomponents. These changes are consistent with the PR's objective to refactor the component architecture.Please verify that the test passes with the updated selectors to confirm they correctly target the DOM elements in the refactored component structure.
Also applies to: 11-11
examples/sites/demos/pc/app/select-wrapper/hide-drop.vue (1)
8-8: No action needed.TinySelectWrappercorrectly supports thehide-dropprop. The component is properly exported with the alias, and the demo correctly applies the prop using Vue's kebab-case binding. The implementation is working as designed.examples/sites/demos/pc/app/select-wrapper/manual-focus-blur.vue (1)
39-39: No changes needed – API compatibility confirmed.TinySelectWrapper fully supports all APIs used in this demo. Both
focus()andblur()methods are properly exposed through the renderless layer, and thefilterableandautomatic-dropdownprops are defined in the component. The import change is correct and maintains full API compatibility.examples/sites/demos/pc/app/select-wrapper/slot-empty.spec.ts (1)
5-5: LGTM! Path update aligns with component migration.The navigation path correctly reflects the move from
selecttoselect-wrapper. The test logic remains unchanged, which indicates the expected behavior and DOM structure are preserved.examples/sites/demos/pc/app/select-wrapper/slot-empty.vue (1)
13-13: The demo file is valid. TinySelectWrapper properly supports the #empty slot through its dynamic slot forwarding mechanism (v-for="slotName in slotNames"), and all underlying components (TinyBaseSelect, TinyTreeSelect, TinyGridSelect) define the #empty slot. The custom empty state rendering will work correctly.examples/sites/demos/pc/app/select-wrapper/native-properties.spec.ts (1)
5-5: Update navigation URL to match select-wrapper component migrationThe change from
select#native-propertiestoselect-wrapper#native-propertiesis correct and aligns with migrating the demo to useTinySelectWrapper. The corresponding demo file atexamples/sites/demos/pc/app/select-wrapper/native-properties.vueexists with the same DOM structure, ensuring all test selectors (.tiny-select,.tiny-input__inner) work correctly without further modifications.examples/sites/demos/pc/app/select-wrapper/clear-no-match-value.spec.ts (1)
5-5: Navigation routes updated correctly for select-wrapper migration.The changes from
select#clear-no-match-valuetoselect-wrapper#clear-no-match-valuehave been verified in both test blocks (lines 5 and 16), and the element selectors are correctly preserved at lines 6 and 17. The test logic remains unchanged and both tests are updated identically, consistent with the demo migration objectives.examples/sites/demos/pc/app/select-wrapper/show-alloption.spec.ts (1)
5-5: Navigation URL updated to select-wrapper demo component.The test now correctly navigates to
select-wrapper#show-alloption. All existing selectors (.tiny-select,.tiny-select-dropdown,.tiny-option) are compatible with the select-wrapper component, as both components maintain the same DOM structure and CSS classes.packages/vue/src/base-select/src/pc.vue (1)
361-361: Panel slot visibility logic correctly enables lazy loading for tree-select and grid-select.The change properly allows the dropdown to render when a panel slot is provided, even if
state.emptyText === false. This is essential for lazy loading where tree/grid panels need to display loading states before data arrives. The complementaryv-if="!slots.panel"guard on line 529 prevents duplicate rendering of empty text.Tree-select and grid-select already use this
#panelslot pattern and will benefit from this change without issues. No backward compatibility concerns identified—components without panel slots retain the previous behavior.examples/sites/demos/pc/app/select-wrapper/nest-radio-grid-much-data.vue (1)
7-7: Grid render type is fully supported by TinySelectWrapper.This change migrates from
TinySelecttoTinySelectWrapper, which is a wrapper component that dynamically routes to TinyGridSelect whenrenderType='grid'. The wrapper properly passes through both therenderTypeprop andgridOpconfiguration to handle the grid layout, radio selection mode, and large dataset (800 items) as demonstrated in this file. The import change is a safe refactoring with no functional impact.packages/vue/src/base-select/src/mobile-first.vue (1)
378-378: LGTM! Panel slot integration with tree-select is properly implemented.The visibility condition correctly enables custom panel slots for tree-select lazy loading. Both tree-select implementations (mobile-first and pc) provide a panel slot wrapping a tree component with lazy loading support through the lazy, load, and afterLoad props. The logic properly ensures the dropdown shows when either a panel slot is provided OR emptyText is not explicitly false, which aligns with the intended functionality.
The change is consistent with the empty text rendering logic at lines 554-568, which only displays when no panel slot exists, preventing conflicts with custom panel content.
examples/sites/demos/pc/app/select-wrapper/slot-prefix.spec.ts (1)
5-5: LGTM! Navigation path correctly updated.The navigation path change from
select#slot-prefixtoselect-wrapper#slot-prefixcorrectly aligns with the component migration. All test assertions and locators remain unchanged, maintaining consistent test coverage.examples/sites/demos/pc/app/select-wrapper/slot-prefix.vue (1)
11-11: The import and feature usage are correct—no API compatibility issues exist.The TinySelectWrapper fully supports all features used in this demo. It exports
modelValuefor v-model binding,multipleandcollapseTagsprops, and dynamically forwards all named slots (including#prefix) to the underlying TinyBaseSelect component via its slot forwarding mechanism. The aliasing is safe and maintains complete API parity.Likely an incorrect or invalid review comment.
examples/sites/demos/pc/app/select-wrapper/filter-mode.vue (1)
26-26: No issues found.TinySelectandTinySelectWrapperare distinct components, both exported from @opentiny/vue. The file is correctly located in the select-wrapper demo folder and properly importsTinySelectWrapper—the component designed for this folder. The aliasing pattern (TinySelectWrapper as TinySelect) is intentional and consistently used across all select-wrapper demos for convenience, not a migration or deprecation. Both components remain available and functional for their respective use cases.examples/sites/demos/pc/app/select-wrapper/option-group.spec.ts (1)
5-5: LGTM! Test route updated to match component migration.The navigation target correctly updates from
select#option-grouptoselect-wrapper#option-group, aligning with the migration to TinySelectWrapper. All test selectors and assertions remain valid.Please ensure the demo site routing configuration includes the
select-wrapper#option-grouproute and that all tests pass after this change.examples/sites/demos/pc/app/select-wrapper/option-group.vue (1)
61-61: No changes needed—the import and usage are correct.The import properly uses
TinySelectWrapperwith an alias for cleaner template syntax.TinyOptionandTinyOptionGroupare correctly exported and fully compatible with SelectWrapper, as evidenced by consistent usage across multiple demo files in the repository.examples/sites/demos/pc/app/select-wrapper/popup-style-position.spec.ts (1)
5-5: Navigation path correctly updated for select-wrapper migration.The navigation target change from
select#popup-style-positiontoselect-wrapper#popup-style-positionaligns with the component migration pattern.examples/sites/demos/pc/app/select-wrapper/popup-style-position.vue (1)
8-8: No API compatibility issues found. TinySelectWrapper fully supports all props used in the template (v-model, popper-class, popper-append-to-body, placement) with correct bindings and defaults. The import statement is valid and the component usage is compatible.examples/sites/demos/pc/app/select-wrapper/slot-reference.vue (1)
11-11: The import pattern is correct and follows library conventions.
TinySelectWrapperis the official export name for theSelectWrappercomponent from@opentiny/vue(as defined inpackages/vue/index.tsandpackages/vue/pc.ts). This aliasing approach is standard throughout the TinyVue library. The demo correctly uses the#referenceslot withTinySelectWrapper, which is fully supported and consistently used across all select-wrapper demo files.examples/sites/demos/pc/app/select-wrapper/slot-reference.spec.ts (1)
5-5: Route verified and exists.The navigation route
select-wrapper#slot-referenceis correctly configured. The corresponding demo file exists atexamples/sites/demos/pc/app/select-wrapper/slot-reference.vuewith valid DOM structure, and the test locators reference elements that will be present when the demo is loaded.examples/sites/demos/pc/app/select-wrapper/tag-type.spec.ts (1)
5-5: LGTM! Navigation path updated to match component wrapper.The test navigation correctly changes from
select#tag-typetoselect-wrapper#tag-type, aligning with the component migration toTinySelectWrapper. All element selectors remain unchanged, which is appropriate since the DOM structure is preserved.examples/sites/demos/pc/app/select-wrapper/tag-type.vue (1)
8-8: No action required—TinySelectWrapper fully supports all props used in this demo.The component
TinySelectWrapperis properly exported from@opentiny/vueand has identical prop support formodelValue,multiple, andtagTypeas the standardSelectcomponent. The import alias and template usage are correct and compatible.Likely an incorrect or invalid review comment.
packages/renderless/src/base-select/index.ts (3)
68-68: No action required. Thevmparameter addition todefaultOnQueryChangeis not a breaking change. The parameter is correctly captured in the factory function's closure inbase-select/vue.ts(line 484) wherevmis passed. All callers ofapi.defaultOnQueryChange(value, isInput)remain unchanged.
75-75: The panel slot detection guard already works reliably across component types. Tree-select properly defines and uses the panel slot in bothpc.vueandmobile-first.vue, rendering a custom<tiny-tree>component within it. When the panel slot is present, the!vm.$slots?.panelcheck correctly prevents automaticremoteMethodinvocation, allowing tree-select to manage remote searches through its own logic. The optional chaining syntax ensures safe access across all components extending base-select.
70-78: Complex conditional flow prioritizes filterMethod with guarded remoteMethod fallback.The restructured logic now calls
filterMethodfirst when available, followed by a conditionalremoteMethodcall only whenremoteis true,remoteMethodexists, and no panel slot is present. However, the claim about duplicate API calls with grid-select is misleading—grid-select'sfilterMethodperforms client-side filtering on full data and doesn't invoke remote searches internally. The panel slot guard (!vm.$slots?.panel) is specifically for tree-select lazy loading compatibility.The execution flow is more complex than before. Consider:
- Documenting the intent that this change supports tree-select lazy loading while maintaining backward compatibility
- Clarifying that grid-select's filterMethod operates client-side only
- Evaluating whether the panel slot detection is the most reliable guard across all use cases and Vue versions
examples/sites/demos/pc/app/select-wrapper/events.spec.ts (1)
5-5: LGTM: Navigation updated to reflect demo migration.The navigation target correctly points to
select-wrapper#events, aligning with the migration of select demos to use TinySelectWrapper.Also applies to: 37-37
examples/sites/demos/pc/app/select-wrapper/remote-method.spec.ts (2)
5-5: LGTM! Navigation updated to select-wrapper route.The navigation changes consistently update all three tests to use the
select-wrapper#remote-methodroute, aligning with the PR's migration of select-wrapper demos to use TinySelectWrapper.Also applies to: 27-27, 56-56
31-31: Selectors are correct and intentionally different by component design.The test uses appropriate selectors for each scenario: single-select tests (lines 9, 60) correctly use
.tiny-input__innerbecause they render through the TinyInput wrapper component, while the multi-select test (line 31) correctly uses.tiny-base-select__inputfor the inline filtering input. This difference reflects the intended DOM structure variation between single and multiple selection modes, not an incomplete migration.Likely an incorrect or invalid review comment.
examples/sites/demos/pc/app/select-wrapper/slot-default.spec.ts (1)
5-5: LGTM! Navigation target updated consistently.The test navigation has been updated to align with the component migration to
TinySelectWrapper. The unchanged test selectors and assertions indicate that the wrapper maintains DOM compatibility.examples/sites/demos/pc/app/select-wrapper/copy-single.spec.ts (1)
5-5: LGTM! Consistent navigation updates across all test cases.All three test cases have been updated to navigate to the wrapper-based route. The test logic remains unchanged, indicating DOM compatibility.
Also applies to: 29-29, 56-56
examples/sites/demos/pc/app/select-wrapper/collapse-tags.vue (1)
29-29: Import aliasing maintains template compatibility.The import has been systematically updated to use
TinySelectWrapperwith theTinySelectalias, ensuring all three select instances in the template continue to work without modification.examples/sites/demos/pc/app/select-wrapper/is-drop-inherit-width.spec.ts (1)
5-5: LGTM! Navigation updates are consistent.Both test cases have been updated to navigate to the wrapper-based route. The dropdown width calculation logic remains unchanged, assuming compatible rendering behavior.
Also applies to: 23-23
examples/sites/demos/pc/app/select-wrapper/memoize-usage.spec.ts (1)
5-5: LGTM! Navigation target updated.The test has been updated to navigate to the wrapper-based route while preserving all caching validation logic.
examples/sites/demos/pc/app/select-wrapper/remote-method.vue (1)
106-106: Import aliasing preserves complex remote search functionality.The import has been updated to use
TinySelectWrapperwith theTinySelectalias. This allows all six remote search scenarios in the template to continue working without modification, including the variousremote-methodandremote-configconfigurations.examples/sites/demos/pc/app/select-wrapper/multiple.spec.ts (1)
5-5: LGTM! Navigation updates maintain test coverage.Both test cases have been updated to navigate to the wrapper-based route. The multiple selection logic and limit validation remain unchanged, ensuring consistent test coverage.
Also applies to: 30-30
examples/sites/demos/pc/app/select-wrapper/memoize-usage.vue (1)
21-21: Import aliasing is correct and migration pattern is clean.
TinySelectWrapperprovides full API compatibility with the original component through a proxy pattern that usesv-bind="mergedProps"andv-on="listeners"to forward all props, events, and slots. This ensures v-model, options, event handlers, and custom attributes work as expected.examples/sites/demos/pc/app/select-wrapper/collapse-tags.spec.ts (1)
5-5: LGTM!The navigation path update from
select#collapse-tagstoselect-wrapper#collapse-tagscorrectly aligns with the component migration toTinySelectWrapper.examples/sites/demos/pc/app/select-wrapper/slot-header-footer.vue (1)
18-18: LGTM!The import aliasing to
TinySelectWrapperis consistent with the broader refactoring. The template uses standard slot features (#dropdown,#footer) which should be well-supported.examples/sites/demos/pc/app/select-wrapper/show-alloption.vue (1)
8-8: LGTM!The import aliasing maintains template compatibility while switching to
TinySelectWrapper. The demo uses standard props that should be well-supported.examples/sites/demos/pc/app/select-wrapper/is-drop-inherit-width.vue (1)
18-18: LGTM!The import aliasing to
TinySelectWrapperis consistent with the migration pattern. The demo showcases dropdown width behavior which should work correctly with the wrapper component.examples/sites/demos/pc/app/select-wrapper/cache-usage.spec.ts (1)
5-5: LGTM!The navigation path correctly updated to
select-wrapper#cache-usageto align with the component migration.examples/sites/demos/pc/app/select-wrapper/slot-label.vue (1)
22-22: LGTM!The import aliasing maintains compatibility while using
TinySelectWrapper. The#labelslot for custom rendering is a standard feature that should be well-supported.examples/sites/demos/pc/app/select-wrapper/nest-grid-disable.vue (1)
57-57: TinySelectWrapper fully supports grid-specific rendering props.The component explicitly defines
renderType,gridOp,radioConfig, andselectConfigin its prop interface, with proper default values and rendering logic in place. The demo file demonstrates working implementation of all these props. The import alias does not affect functionality.Likely an incorrect or invalid review comment.
examples/sites/demos/pc/app/select-wrapper/copy-multi.vue (1)
44-44: TinySelectWrapper supports all copy-related props.The component definition in
packages/vue/src/select-wrapper/src/pc.vueincludes all three props mentioned in the demo:tagSelectable(used astag-selectable),copyable, andtextSplit(used astext-split). The import alias is valid, and all props are correctly utilized in the demo file.examples/sites/demos/pc/app/select-wrapper/size.vue (1)
25-25: LGTM! Systematic refactor to use TinySelectWrapper.The aliasing of TinySelectWrapper as TinySelect maintains backward compatibility in the template while switching to the wrapper implementation. This pattern is consistently applied across multiple select-wrapper demos in this PR.
examples/sites/demos/pc/app/select-wrapper/size.spec.ts (1)
5-5: LGTM! Navigation updates aligned with component changes.The test navigation targets have been correctly updated from
select#sizetoselect-wrapper#sizeto match the underlying component switch to TinySelectWrapper. All test logic and assertions remain intact.Also applies to: 18-18, 33-33, 49-49
examples/sites/demos/pc/app/select-wrapper/all-text.vue (1)
16-16: LGTM! Consistent aliasing pattern.The import aliasing follows the same pattern as other select-wrapper demos, switching to TinySelectWrapper while preserving the TinySelect identifier for backward compatibility.
examples/sites/demos/pc/app/select-wrapper/all-text.spec.ts (1)
5-5: LGTM! Test navigation updated correctly.The navigation target has been updated to
select-wrapper#all-textto align with the component wrapper changes.examples/sites/demos/pc/app/select-wrapper/input-box-type.spec.ts (2)
5-5: LGTM! Navigation updates aligned with component wrapper.The test navigation targets have been correctly updated to
select-wrapper#input-box-type.Also applies to: 27-27, 50-50
70-70: Class name update reflects component structure change.The assertion now expects
tiny-base-select__multipleinstead oftiny-select__multiple, which aligns with the internal component refactor to use base-select classes. The test will verify this is correct at runtime.examples/sites/demos/pc/app/tree-select/lazy-composition-api.vue (1)
41-43: afterLoad hook appropriately demonstrates lifecycle.The afterLoad implementation logs the loaded data, which is suitable for a demo that shows developers how to hook into the loading lifecycle.
examples/sites/demos/pc/app/select-wrapper/show-tip.vue (1)
8-8: LGTM! Consistent with refactor pattern.The import aliasing follows the established pattern across select-wrapper demos.
examples/sites/demos/pc/app/select-wrapper/input-box-type.vue (1)
26-26: LGTM! Completes the consistent refactor pattern.The import aliasing is consistent with all other select-wrapper demos, completing the systematic migration to TinySelectWrapper.
examples/sites/demos/pc/app/select-wrapper/slot-default.vue (1)
37-37: LGTM!The import alias change from
TinySelecttoTinySelectWrapper as TinySelectaligns with the project-wide migration pattern observed across other select-wrapper demo files.packages/vue/src/tree-select/src/mobile-first.vue (1)
162-169: LGTM!The lazy loading props are well-defined with appropriate types and defaults, consistent with the main component definition in
index.ts.examples/sites/demos/pc/app/tree-select/lazy-multiple.vue (1)
1-65: LGTM!This demo effectively illustrates the new lazy loading feature with multiple selection. The console.log statements serve as helpful documentation for developers learning the API, and the random delays appropriately simulate async data fetching.
packages/vue/src/tree-select/src/index.ts (1)
103-110: LGTM!The new lazy loading props (
lazy,load,afterLoad) are well-defined and extend the component's public API appropriately. The types and defaults are consistent with the template implementations inpc.vueandmobile-first.vue.packages/vue/src/tree-select/src/pc.vue (1)
105-112: LGTM!The lazy loading prop definitions are consistent with
index.tsandmobile-first.vue, maintaining API uniformity across the component variants.examples/sites/demos/pc/app/select-wrapper/copy-multi.spec.ts (1)
5-52: LGTM! Navigation targets and selectors updated consistently.The test navigation targets have been correctly updated from
select#copy-multitoselect-wrapper#copy-multi, and the copy icon selector has been updated from.tiny-select__copyto.tiny-base-select__copy. These changes align with the broader migration toTinySelectWrapper.examples/sites/demos/pc/app/select-wrapper/nest-grid.spec.ts (1)
5-95: LGTM! Consistent selector updates across all test cases.Navigation targets and caret selectors have been correctly updated throughout the file to use
select-wrapper#nest-gridand.tiny-base-select__caret, maintaining consistency with the wrapper-based component refactoring.examples/sites/demos/pc/app/select-wrapper/init-label.vue (1)
29-29: LGTM! Import alias maintains backward compatibility.The import has been updated to use
TinySelectWrapper as TinySelect, which allows the component to use the wrapper implementation while maintaining the same template syntax and component registration. This is a clean refactoring approach.examples/sites/demos/pc/app/select-wrapper/disabled.spec.ts (1)
5-88: LGTM! Navigation targets updated consistently.All four test cases have been correctly updated to navigate to
select-wrapper#disabledinstead ofselect#disabled, aligning with the component migration.examples/sites/demos/pc/app/select-wrapper/nest-tree.spec.ts (1)
5-84: LGTM! Tree select tests updated consistently.Navigation targets and caret selectors have been properly updated across all three test cases to use
select-wrapper#nest-treeand.tiny-base-select__caret, maintaining consistency with the wrapper migration.examples/sites/demos/pc/app/select-wrapper/optimization.spec.ts (1)
5-46: LGTM! Virtual scrolling tests updated.Both virtual scrolling test cases have been correctly updated to navigate to
select-wrapper#optimization.examples/sites/demos/pc/app/select-wrapper/automatic-dropdown.spec.ts (1)
5-31: LGTM! Improved selector specificity.Navigation targets updated correctly. Additionally, the option selection strategy has been improved by using
dropdown.locator('.tiny-option')instead ofpage.getByRole('listitem'), which provides better scope and specificity for the dropdown options.examples/sites/demos/pc/app/select-wrapper/nest-grid-disable.spec.ts (1)
5-41: LGTM! Navigation targets updated consistently.Both test cases have been correctly updated to navigate to
select-wrapper#nest-grid-disable.examples/sites/demos/pc/app/select-wrapper/basic-usage.spec.ts (1)
5-5: Test updates align with component migration.The navigation target and selector updates correctly reflect the migration from TinySelect to TinySelectWrapper. The switch from ARIA role-based selectors to CSS class-based selectors (
.tiny-option) is consistent throughout the test suite.Also applies to: 9-9, 16-16, 28-28, 39-39
examples/sites/demos/pc/app/select-wrapper/binding-obj.spec.ts (1)
5-5: LGTM!Test navigation and selector updates correctly reflect the component migration to select-wrapper.
Also applies to: 13-13, 18-18
examples/sites/demos/pc/app/select-wrapper/native-properties.vue (1)
8-8: Verify API compatibility between TinySelectWrapper and TinySelect.This file follows the same import aliasing pattern as other demos in this PR. Ensure TinySelectWrapper is fully compatible with TinySelect's API surface (props, events, slots, methods).
examples/sites/demos/pc/app/select-wrapper/clearable.spec.ts (1)
5-5: LGTM!Test updates properly reflect the select-wrapper component migration.
Also applies to: 19-19
examples/sites/demos/pc/app/select-wrapper/nest-grid-remote.vue (1)
63-63: Verify API compatibility between TinySelectWrapper and TinySelect.This follows the same import aliasing pattern as other select-wrapper demos. Verify compatibility as noted in earlier comments.
examples/sites/demos/pc/app/select-wrapper/extra-query-params.vue (1)
47-47: Verify API compatibility between TinySelectWrapper and TinySelect.Import aliasing follows the established pattern. Verify TinySelectWrapper compatibility as discussed in earlier comments.
examples/sites/demos/pc/app/select-wrapper/nest-grid-init-query.vue (1)
45-45: Verify API compatibility between TinySelectWrapper and TinySelect.This is the final demo file following the import aliasing pattern. Ensure TinySelectWrapper maintains full API compatibility with TinySelect.
examples/sites/demos/pc/app/select-wrapper/multiple-mix.vue (1)
20-20: SelectWrapper is intentionally designed as a component adapter, not a direct alias for Select.TinySelectWrapper (SelectWrapper) is a wrapper component that dynamically delegates to TinyBaseSelect, TinyTreeSelect, or TinyGridSelect based on the
renderTypeprop. While the import aliasing patternTinySelectWrapper as TinySelectis used consistently across select-wrapper demos, note that there are API differences:
- Prop naming:
inputBoxType(SelectWrapper) vsInputBoxType(Select)- Default values:
'normal'vs'input'respectivelyThis demo currently uses only common compatible props (
options,multiple,hover-expand,display-only), so it functions correctly. However, be aware that if specific Select-only properties are introduced, they may not be available in SelectWrapper.examples/sites/demos/pc/app/select-wrapper/allow-create.spec.ts (1)
6-6: Navigation path updated to select-wrapper scope.The test now navigates to
select-wrapper#allow-createinstead ofselect#allow-create, aligning with the component wrapper migration.examples/sites/demos/pc/app/select-wrapper/multiple.vue (1)
103-103: Verify advanced multi-select features with TinySelectWrapper.This demo exercises extensive multi-select functionality including
collapse-tags,hover-expand,click-expand,show-all-text-tag,multiple-limit, and required/disabled options. Ensure all features work correctly with the wrapper implementation.examples/sites/demos/pc/app/select-wrapper/copy-single.vue (1)
35-35: This concern is incorrect. TinySelectWrapper intentionally exposes child component state via a Proxy pattern, withcachedOptionsexplicitly mentioned in code comments as part of the public API. Multiple official demos consistently use this pattern, confirming it is the designed approach for accessing cached options.Likely an incorrect or invalid review comment.
examples/sites/demos/pc/app/select-wrapper/nest-grid.vue (1)
41-41: No action required. TinySelectWrapper properly supportsrender-type="grid"and thegrid-opprop. The component defines both props (renderType and gridOp) with appropriate defaults, imports TinyGridSelect for grid rendering, and the demo in nest-grid.vue demonstrates three working scenarios: single selection, multi-selection, and filterable grid rendering.examples/sites/demos/pc/app/tree-select/lazy-multiple-composition-api.vue (1)
1-58: LGTM! Lazy loading demo is well-implemented.The composition API demo correctly demonstrates lazy loading with multiple selection. The load function properly handles both initial and subsequent loads, and the random disabled/isLeaf flags effectively showcase dynamic node properties.
examples/sites/demos/pc/app/tree-select/webdoc/tree-select.js (1)
71-84: LGTM! Complete demo documentation.The lazy loading demo entry is properly documented with both Chinese and English descriptions, correctly formatted, and appropriately positioned in the demos array.
examples/sites/demos/mobile-first/app/tree-select/lazy.vue (1)
1-59: LGTM! Mobile-first lazy loading demo is well-implemented.The demo correctly implements lazy loading for mobile-first context. The load function properly handles both initial and subsequent node loads, and the attribute selector styles are appropriate for mobile-first components.
examples/sites/demos/pc/app/select-wrapper/disabled.vue (1)
71-71: SelectWrapper migration is verified as API-compatible. SelectWrapper is properly exported as TinySelectWrapper and provides full API compatibility with comprehensive props forwarding and slot delegation. All demo scenarios (disabled states, multiple selection, hover-expand, etc.) function correctly without changes.examples/sites/demos/pc/app/select-wrapper/nest-grid-remote.spec.ts (3)
6-6: LGTM on URL migrations.The navigation targets have been consistently updated from
select#nest-grid-remotetoselect-wrapper#nest-grid-remoteacross all test blocks.Also applies to: 42-42, 72-72, 104-104
12-12: Selector updates align with base-select component structure.The class selectors have been correctly updated from
.tiny-select__caretto.tiny-base-select__caretand.tiny-select__inputto.tiny-base-select__input, consistent with the TinySelectWrapper migration.Also applies to: 48-48, 75-77, 108-110
27-28: Verify trimmed row name expectations match actual data.The row name patterns changed from including trailing numbers (e.g.,
'省份 1 城市 1 区域 1') to trimmed forms ('省份 1 城市 1 区域'). Ensure these match the actual grid data rendered by the demo; otherwise, the test assertions will fail.examples/sites/demos/pc/app/tree-select/lazy.vue (1)
36-44: Demo logic is clear and appropriately randomized.The random
disabledandisLeafflags effectively demonstrate the lazy loading flexibility. The simulated async delay viasetTimeoutclearly shows how to integrate with real API calls.examples/sites/demos/pc/app/select-wrapper/events.vue (1)
38-38: Import alias maintains template compatibility.Using
TinySelectWrapper as TinySelectallows the demo to use the new wrapper component without requiring template changes. This is a clean migration pattern.examples/sites/demos/apis/tree-select.js (1)
268-279: Lazy loading API documentation is well-structured.The prop definitions include appropriate defaults, bilingual descriptions, and demo references for both pc and mobile-first modes.
| { | ||
| demoId: 'lazy', | ||
| name: { | ||
| 'zh-CN': '懒加载', | ||
| 'en-US': 'Lazy loading' | ||
| }, | ||
| desc: { | ||
| 'zh-CN': | ||
| '通过 <code>lazy</code> 属性,启用懒加载模式。<br>通过 <code>load</code> 函数属性,触发加载,初始会执行一次。<br>通过 <code>after-load</code> 函数属性,监听下级节点加载完毕的事件。' | ||
| }, | ||
| codeFiles: ['lazy.vue'] | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing en-US description.
The new lazy demo entry is missing the en-US description (Line 80), while the zh-CN description is complete. The PC version of this file (examples/sites/demos/pc/app/tree-select/webdoc/tree-select.js) includes both translations. Add the en-US description for i18n completeness.
🔎 Apply this diff to add the missing en-US description:
desc: {
'zh-CN':
- '通过 <code>lazy</code> 属性,启用懒加载模式。<br>通过 <code>load</code> 函数属性,触发加载,初始会执行一次。<br>通过 <code>after-load</code> 函数属性,监听下级节点加载完毕的事件。'
+ '通过 <code>lazy</code> 属性,启用懒加载模式。<br>通过 <code>load</code> 函数属性,触发加载,初始会执行一次。<br>通过 <code>after-load</code> 函数属性,监听下级节点加载完毕的事件。',
+ 'en-US':
+ 'Enable lazy loading mode with the <code>lazy</code> property. <br>load is triggered by the <code>load</code> function property, which is initially executed once. <br>afterLoad </code> function properties are used to listen for events when a subordinate node has finished loading.'
},🤖 Prompt for AI Agents
In examples/sites/demos/mobile-first/app/tree-select/webdoc/tree-select.js
around lines 71 to 82, the demo entry for 'lazy' has a zh-CN description but is
missing the en-US description; add an 'en-US' field mirroring the zh-CN content
in English (e.g. "Enable lazy loading via the <code>lazy</code> prop. Use the
<code>load</code> function prop to trigger loading — it runs once initially. Use
the <code>after-load</code> function prop to listen for when child nodes finish
loading.") so both locales are present for i18n completeness.
|
|
||
| <script> | ||
| import { TinySelect, TinyOption } from '@opentiny/vue' | ||
| import { TinySelectWrapper as TinySelect, TinyOption } from '@opentiny/vue' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for TinySelectWrapper and TinySelect in the repository
# First, find the main export files for these components
echo "=== Searching for TinySelectWrapper definition ==="
fd -t f "select-wrapper" -i | head -20
echo -e "\n=== Searching for TinySelect definition ==="
fd -t f "select" -i | grep -v node_modules | grep -v dist | head -20
echo -e "\n=== Looking for export statements with TinySelectWrapper ==="
rg -n "export.*TinySelectWrapper" --type=ts --type=vue
echo -e "\n=== Looking for export statements with TinySelect ==="
rg -n "export.*TinySelect" --type=ts --type=vue | grep -v TinySelectWrapper | head -10Repository: opentiny/tiny-vue
Length of output: 1958
🏁 Script executed:
#!/bin/bash
# Let's find the actual component source code
echo "=== Finding package structure ==="
ls -la packages/ | head -20
echo -e "\n=== Searching for select-wrapper component source ==="
find . -path ./node_modules -prune -o -path ./dist -prune -o -type f -name "*select-wrapper*" -print | head -20
echo -e "\n=== Searching for select component source ==="
find . -path ./node_modules -prune -o -path ./dist -prune -o -type f -name "*select.vue" -o -name "*select.ts" -print | grep -E "packages|src" | head -20
echo -e "\n=== Looking in vue package ==="
ls -la packages/vue/src/components/ | grep -i selectRepository: opentiny/tiny-vue
Length of output: 2090
🏁 Script executed:
#!/bin/bash
# Let's explore the vue package structure
echo "=== Structure of packages/vue ==="
ls -la packages/vue/src/
echo -e "\n=== Looking for select components ==="
ls -la packages/vue/src/
echo -e "\n=== Find all select-related files ==="
find packages/vue -name "*select*" -type f 2>/dev/null | grep -v node_modules | head -20
echo -e "\n=== Find select.ts or select.vue in packages ==="
find packages -name "select.ts" -o -name "select.vue" 2>/dev/null | grep -v node_modules | head -20Repository: opentiny/tiny-vue
Length of output: 25878
🏁 Script executed:
#!/bin/bash
# Let's look at what files are in select and select-wrapper directories
echo "=== Files in select directory ==="
ls -la packages/vue/src/select/
echo -e "\n=== Files in select-wrapper directory ==="
ls -la packages/vue/src/select-wrapper/
echo -e "\n=== Content of select-wrapper index ==="
cat packages/vue/src/select-wrapper/index.ts 2>/dev/null || echo "Not found"
echo -e "\n=== Content of select index ==="
cat packages/vue/src/select/index.ts 2>/dev/null || echo "Not found"Repository: opentiny/tiny-vue
Length of output: 2814
🏁 Script executed:
#!/bin/bash
# Let's check the src directories
echo "=== Files in select/src ==="
ls -la packages/vue/src/select/src/
echo -e "\n=== Files in select-wrapper/src ==="
ls -la packages/vue/src/select-wrapper/src/
echo -e "\n=== Content of select-wrapper/src/index.vue ==="
head -100 packages/vue/src/select-wrapper/src/index.vue 2>/dev/null || echo "Not found"
echo -e "\n=== Content of select/src/index.vue ==="
head -100 packages/vue/src/select/src/index.vue 2>/dev/null || echo "Not found"Repository: opentiny/tiny-vue
Length of output: 941
🏁 Script executed:
#!/bin/bash
# Let's check the index.ts files which contain the actual component logic
echo "=== Content of select-wrapper/src/index.ts ==="
cat packages/vue/src/select-wrapper/src/index.ts
echo -e "\n=== Content of select/src/index.ts (first 150 lines) ==="
head -150 packages/vue/src/select/src/index.tsRepository: opentiny/tiny-vue
Length of output: 10964
🏁 Script executed:
#!/bin/bash
# Let's get the complete select/src/index.ts to compare props
echo "=== Full content of select/src/index.ts ==="
cat packages/vue/src/select/src/index.tsRepository: opentiny/tiny-vue
Length of output: 7658
🏁 Script executed:
#!/bin/bash
# Let's compare the props more carefully - let me extract and compare them
echo "=== Analyzing prop differences ==="
python3 << 'EOF'
import re
# Read both files
with open('packages/vue/src/select-wrapper/src/index.ts', 'r') as f:
wrapper_content = f.read()
with open('packages/vue/src/select/src/index.ts', 'r') as f:
select_content = f.read()
# Extract props section
wrapper_props = re.search(r'props:\s*\{(.*?)\n \},', wrapper_content, re.DOTALL)
select_props = re.search(r'props:\s*\{(.*?)\n \},', select_content, re.DOTALL)
if wrapper_props and select_props:
wrapper_text = wrapper_props.group(1)
select_text = select_props.group(1)
# Find differences by comparing line by line
wrapper_lines = set(wrapper_text.strip().split('\n'))
select_lines = set(select_text.strip().split('\n'))
only_in_wrapper = wrapper_lines - select_lines
only_in_select = select_lines - wrapper_lines
if only_in_wrapper or only_in_select:
print("Props ONLY in SelectWrapper:")
for line in sorted(only_in_wrapper):
if line.strip():
print(f" {line.strip()}")
print("\nProps ONLY in Select:")
for line in sorted(only_in_select):
if line.strip():
print(f" {line.strip()}")
else:
print("All props are identical between SelectWrapper and Select")
else:
print("Could not parse props")
EOFRepository: opentiny/tiny-vue
Length of output: 147
🏁 Script executed:
#!/bin/bash
# Let's do a simple diff instead
echo "=== Diff between select-wrapper and select props ==="
diff -u <(sed -n '/props: {/,/},/p' packages/vue/src/select/src/index.ts | grep -E "^\s+(.*?):" | head -50) <(sed -n '/props: {/,/},/p' packages/vue/src/select-wrapper/src/index.ts | grep -E "^\s+(.*?):" | head -50)
echo -e "\n=== Check for InputBoxType vs inputBoxType ==="
grep -n "inputBoxType\|InputBoxType" packages/vue/src/select/src/index.ts
grep -n "inputBoxType\|InputBoxType" packages/vue/src/select-wrapper/src/index.tsRepository: opentiny/tiny-vue
Length of output: 314
🏁 Script executed:
#!/bin/bash
# Let's check the exact lines around the InputBoxType/inputBoxType difference
echo "=== Select InputBoxType (lines 325-335) ==="
sed -n '325,335p' packages/vue/src/select/src/index.ts
echo -e "\n=== SelectWrapper inputBoxType (lines 325-335) ==="
sed -n '325,335p' packages/vue/src/select-wrapper/src/index.ts
echo -e "\n=== Component names ==="
echo "Select name:"
grep "name: \$prefix" packages/vue/src/select/src/index.ts
echo "SelectWrapper name:"
grep "name: \$prefix" packages/vue/src/select-wrapper/src/index.tsRepository: opentiny/tiny-vue
Length of output: 782
API Incompatibility: TinySelectWrapper does not fully implement TinySelect interface.
The import alias does not guarantee API compatibility. Verified differences:
- Property name mismatch:
InputBoxType(Select) vsinputBoxType(SelectWrapper) — case-sensitive, will cause prop binding failures - Default value mismatch:
'input'(Select) vs'normal'(SelectWrapper) for the box type property
These breaking changes risk silent bugs where templates work but props are ignored. Either ensure TinySelectWrapper props match TinySelect exactly, or document that this is not a drop-in replacement.
| await page.waitForTimeout(200) | ||
| await input.hover() | ||
| await select.locator('.tiny-select__caret.tiny-select__close').click() | ||
| await page.getByLabel('示例', { exact: true }).getByRole('img').first().click() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Get the test file content around line 29
head -n 40 examples/sites/demos/pc/app/select-wrapper/events.spec.ts | tail -n +15Repository: opentiny/tiny-vue
Length of output: 1126
🏁 Script executed:
#!/bin/bash
# Find the select-wrapper component files
find examples/sites/demos/pc/app/select-wrapper -type f \( -name "*.vue" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" \) | head -20Repository: opentiny/tiny-vue
Length of output: 1584
🏁 Script executed:
#!/bin/bash
# Look at the events composition API component
cat -n examples/sites/demos/pc/app/select-wrapper/events-composition-api.vue | head -100Repository: opentiny/tiny-vue
Length of output: 2725
🏁 Script executed:
#!/bin/bash
# Search for the TinySelectWrapper component implementation
find . -type f -name "*.vue" -o -name "*.ts" -o -name "*.tsx" | xargs grep -l "TinySelectWrapper\|SelectWrapper" | grep -v node_modules | grep -v demos | head -10Repository: opentiny/tiny-vue
Length of output: 293
🏁 Script executed:
#!/bin/bash
# Look at the PC select-wrapper component structure
cat -n packages/vue/src/select-wrapper/src/pc.vue | head -150Repository: opentiny/tiny-vue
Length of output: 4367
🏁 Script executed:
#!/bin/bash
# Find the BaseSelect component
find . -type f -path "*/vue-base-select*" -name "*.vue" | head -5Repository: opentiny/tiny-vue
Length of output: 43
🏁 Script executed:
#!/bin/bash
# Search for base-select implementation
find . -type f -name "*base-select*" | grep -v node_modules | head -10Repository: opentiny/tiny-vue
Length of output: 529
🏁 Script executed:
#!/bin/bash
# Find the actual base-select Vue component in packages
find packages -type f -name "*.vue" | xargs grep -l "clear\|caret" | grep -i select | head -10Repository: opentiny/tiny-vue
Length of output: 527
🏁 Script executed:
#!/bin/bash
# Look at base-select PC component for the clear button structure
cat -n packages/vue/src/base-select/src/pc.vue | grep -A 10 -B 10 "clear\|caret" | head -80Repository: opentiny/tiny-vue
Length of output: 3870
🏁 Script executed:
#!/bin/bash
# Look at the full base-select to understand icon structure better
cat -n packages/vue/src/base-select/src/pc.vue | sed -n '320,355p'Repository: opentiny/tiny-vue
Length of output: 1825
🏁 Script executed:
#!/bin/bash
# Look at the full test file to see if there are any setup/context clues
wc -l examples/sites/demos/pc/app/select-wrapper/events.spec.tsRepository: opentiny/tiny-vue
Length of output: 121
🏁 Script executed:
#!/bin/bash
# View the full test file
cat -n examples/sites/demos/pc/app/select-wrapper/events.spec.tsRepository: opentiny/tiny-vue
Length of output: 3423
Refine the clear button locator to avoid ambiguity with .first().
The semantic locator refactor (getByLabel + getByRole) follows best practices, but multiple image elements match this chain (the copy and close icons). Using .first() is not recommended because when your page changes, Playwright may click on an element you did not intend; instead, create a locator that uniquely identifies the target element.
Consider using a more specific identifier such as a data-testid attribute on the icon-close component, or chaining with a filter to distinguish it from the copy icon.
🤖 Prompt for AI Agents
In examples/sites/demos/pc/app/select-wrapper/events.spec.ts around line 29, the
test uses .first() on a semantic locator which can click the wrong image when
DOM changes; replace the ambiguous selector by targeting the clear/close icon
uniquely—add a stable identifier (e.g., data-testid or a distinct accessible
name) to the icon-close component in the app markup, then update the test to use
a locator that targets that identifier (or chain a more specific
filter/accessible-name on getByRole) instead of .first(), ensuring the test
reliably clicks the intended clear button.
| test('默认搜索', async ({ page }) => { | ||
| page.on('pageerror', (exception) => expect(exception).toBeNull()) | ||
| await page.goto('select#filter-method') | ||
| await page.goto('select-wrapper#filter-method') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
fd -t f "filter-method.spec.ts"Repository: opentiny/tiny-vue
Length of output: 303
🏁 Script executed:
cat -n "examples/sites/demos/pc/app/select-wrapper/filter-method.spec.ts"Repository: opentiny/tiny-vue
Length of output: 3581
🏁 Script executed:
# Check if select-wrapper route directory exists
fd -t d "select-wrapper" examples/sites/demos/pc/app/
# List the structure of select-wrapper
ls -la "examples/sites/demos/pc/app/select-wrapper/" 2>/dev/null | head -20Repository: opentiny/tiny-vue
Length of output: 1495
🏁 Script executed:
# Check if filter-method.vue exists in select-wrapper
ls -la "examples/sites/demos/pc/app/select-wrapper/" | grep filter-method
# Also check the original select folder for comparison
ls -la "examples/sites/demos/pc/app/select/" | grep filter-methodRepository: opentiny/tiny-vue
Length of output: 514
🏁 Script executed:
# Check the demo file in select-wrapper to see the structure
cat -n "examples/sites/demos/pc/app/select-wrapper/filter-method.vue" | head -50Repository: opentiny/tiny-vue
Length of output: 1500
🏁 Script executed:
# Get the full filter-method.vue to see if it has id="filter-method"
cat "examples/sites/demos/pc/app/select-wrapper/filter-method.vue"Repository: opentiny/tiny-vue
Length of output: 1868
🏁 Script executed:
# Check the select (original) filter-method.vue to compare
cat "examples/sites/demos/pc/app/select/filter-method.vue"Repository: opentiny/tiny-vue
Length of output: 1847
🏁 Script executed:
# Check if other demo files in select-wrapper have id attributes in their templates
grep -r "id=" "examples/sites/demos/pc/app/select-wrapper/" --include="*.vue" | head -10
# Also check in select folder
grep -r "id=" "examples/sites/demos/pc/app/select/" --include="*.vue" | head -10Repository: opentiny/tiny-vue
Length of output: 43
🏁 Script executed:
# Search for where the demo routing/layout might add the id attribute
fd -t f "layout" "examples/sites/demos/pc/app/" -o | head -20
# Also look for index files that might render demos
find "examples/sites/demos/pc/app/" -name "index.vue" -o -name "index.ts" | head -10
# Check the playwright config to understand how routes work
find "examples/sites/demos/" -name "playwright.config.*" -o -name "*.config.ts"Repository: opentiny/tiny-vue
Length of output: 177
🏁 Script executed:
# Look for playwright config
find "examples/sites/demos/" -name "playwright.config.*"
# Check how the demo site renders - look for main app file
ls -la "examples/sites/demos/pc/" | head -20Repository: opentiny/tiny-vue
Length of output: 543
🏁 Script executed:
# Check the config and menus to understand routing
cat "examples/sites/demos/pc/config.js"
# Check menus
head -100 "examples/sites/demos/pc/menus.js"Repository: opentiny/tiny-vue
Length of output: 2344
🏁 Script executed:
# Look for how demo pages are rendered/wrapped - check for router or app setup
find "examples/sites/demos/pc/" -name "*.vue" -o -name "*.ts" | grep -E "(app|main|index)" | head -10
# Check if there's a demo wrapper that adds IDs
grep -r "id=" "examples/sites/demos/pc/" --include="*.vue" --include="*.ts" | grep -E "(demo|wrapper)" | head -5
# Let's check one of the working tests to see if they have IDs
cat "examples/sites/demos/pc/app/select/filter-method.spec.ts" | head -20Repository: opentiny/tiny-vue
Length of output: 2015
🏁 Script executed:
# Look at how the demo site is structured - check for layout or wrapper components
find "examples/sites/demos/pc/" -type f -name "*.vue" | xargs grep -l "slot\|component" | head -5
# Check if there's a main or layout file in the app directory
ls -la "examples/sites/demos/pc/app/" | grep -E "(App|Layout|Main|index)"
# Look for the build/render setup for demos
find "examples/sites/demos/" -name "vite.config.*" -o -name "*.config.ts" | head -5Repository: opentiny/tiny-vue
Length of output: 377
🏁 Script executed:
# Search for where demo pages get their IDs - look for dynamic route setup
grep -r "filter-method" "examples/sites/demos/" --include="*.ts" --include="*.js" --include="*.vue" | grep -v ".spec.ts" | head -10
# Check if there's a docs/framework site file
find "examples/sites/" -maxdepth 3 -name "*.vue" -o -name "*.ts" | grep -E "(site|main|app)" | head -10Repository: opentiny/tiny-vue
Length of output: 1192
🏁 Script executed:
# Check the select-wrapper API definition
grep -A 20 "select-wrapper" "examples/sites/demos/apis/base-select.js" | head -30
# Also check if select-wrapper has its own API file
find "examples/sites/demos/apis/" -name "*select*" -type f
# Look at how demos are indexed
head -50 "examples/sites/demos/apis/base-select.js"Repository: opentiny/tiny-vue
Length of output: 2246
🏁 Script executed:
# Check the select-wrapper API file
head -100 "examples/sites/demos/apis/select-wrapper.js"Repository: opentiny/tiny-vue
Length of output: 3774
Add missing id="filter-method" wrapper to demo template.
The test file references an element with id="filter-method" (lines 6, 50) via page.locator('#filter-method'), but the demo file examples/sites/demos/pc/app/select-wrapper/filter-method.vue does not contain this ID attribute. Wrap the template content in a <div id="filter-method"> to match what the tests expect.
🤖 Prompt for AI Agents
In examples/sites/demos/pc/app/select-wrapper/filter-method.spec.ts around line
5 the test navigates to 'select-wrapper#filter-method', but the demo component
file examples/sites/demos/pc/app/select-wrapper/filter-method.vue lacks the
expected wrapper id; edit that .vue file and wrap the root template content in a
<div id="filter-method"> ... </div> (ensuring you close the div and keep
existing template structure/indentation intact) so the
page.locator('#filter-method') in the tests can find the element.
| const wrap = page.locator('#popup-style-position') | ||
| const select = wrap.locator('.tiny-select') | ||
| const dropdown = select.locator('.tiny-select__tags-group > .tiny-select-dropdown') | ||
| const dropdown = page.locator('.tiny-select-dropdown') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check file structure related to select-wrapper
fd "select-wrapper" --type f | head -20
# Look for the test file and related files
ls -la examples/sites/demos/pc/app/select-wrapper/ 2>/dev/null || echo "Directory not found, searching..."
# Search for select-wrapper files in the repo
find . -path "*select-wrapper*" -type f | grep -E "\.(vue|ts|js)$" | head -20Repository: opentiny/tiny-vue
Length of output: 12472
🏁 Script executed:
#!/bin/bash
# Read the test file mentioned in the review
cat -n examples/sites/demos/pc/app/select-wrapper/popup-style-position.spec.ts
# Read the demo component file
cat -n examples/sites/demos/pc/app/select-wrapper/popup-style-position.vue
# Search for Select/SelectWrapper component definition to understand dropdown rendering
fd -e vue -e ts "Select" packages/components --type f | grep -i "select" | head -10Repository: opentiny/tiny-vue
Length of output: 2027
🏁 Script executed:
#!/bin/bash
# Check if there are multiple select-wrapper instances in the demo or other selects on the page
cat -n examples/sites/demos/pc/app/select-wrapper/popup-style-position.vue | grep -i "tiny-select\|wrap"
# Check what's wrapped by the #popup-style-position id
rg -B 5 -A 5 "popup-style-position" examples/sites/demos/pc/app/select-wrapper/popup-style-position.vue
# Look at page structure to confirm wrap element contains the select
grep -r "id.*popup-style-position\|class.*popup-style-position" examples/sites/demos/pc/app/select-wrapper/Repository: opentiny/tiny-vue
Length of output: 295
🏁 Script executed:
#!/bin/bash
# Search for demo page wrapper or layout that adds ids
rg -B 2 -A 2 "popup-style-position" examples/sites/demos/ --type vue --type ts --type js | head -50
# Check if there's a wrapper component or layout
find examples/sites/demos/pc/app/select-wrapper -name "*.vue" -o -name "*.ts" | xargs grep -l "popup-style-position" 2>/dev/null
# Look for how demo ids are generated
rg "id=" examples/sites/demos/pc/app/select-wrapper/ | head -10Repository: opentiny/tiny-vue
Length of output: 177
🏁 Script executed:
#!/bin/bash
# Check how other select-wrapper tests handle dropdown locators to understand patterns
rg "page.locator.*tiny-select-dropdown\|wrap.locator.*tiny-select-dropdown" examples/sites/demos/pc/app/select-wrapper/ --type ts
# Check a few other spec files to see the pattern
head -20 examples/sites/demos/pc/app/select-wrapper/basic-usage.spec.tsRepository: opentiny/tiny-vue
Length of output: 987
Scope dropdown locator to the component wrapper for proper test isolation.
The current global selector page.locator('.tiny-select-dropdown') is inappropriate for this test because the component explicitly disables popper-append-to-body (set to false on line 2 of the demo), meaning the dropdown renders within the component's DOM. This should be scoped to the wrapper element:
- const dropdown = page.locator('.tiny-select-dropdown')
+ const dropdown = wrap.locator('.tiny-select-dropdown')This ensures the locator targets only the dropdown associated with the test's specific select component, improving reliability and preventing matches against unrelated dropdowns if the test structure changes.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const dropdown = page.locator('.tiny-select-dropdown') | |
| const dropdown = wrap.locator('.tiny-select-dropdown') |
🤖 Prompt for AI Agents
In examples/sites/demos/pc/app/select-wrapper/popup-style-position.spec.ts
around line 9, the test uses page.locator('.tiny-select-dropdown') which is
global; because popper-append-to-body is false the dropdown is rendered inside
the component wrapper, so scope the locator to that wrapper instead. Replace the
global locator with one that targets the specific component wrapper (e.g. obtain
the wrapper locator first and call its locator('.tiny-select-dropdown'), or use
a combined selector like '<wrapper-selector> .tiny-select-dropdown') so the
dropdown is isolated to the component under test.
| state.selectEmitter.emit(constants.COMPONENT_NAME.OptionGroup, constants.EVENT_NAME.queryChange) | ||
| // 如果同时存在 remoteMethod 且没有使用 panel 插槽,也调用 remoteMethod(兼容其他场景) | ||
| if (props.remote && typeof props.remoteMethod === 'function' && !vm.$slots?.panel) { | ||
| state.hoverIndex = -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate hoverIndex reset.
The statement state.hoverIndex = -1 appears in both the new conditional block (line 76) and the fallback condition (line 80), which is redundant.
🔎 Refactor to reduce duplication:
Consider extracting the hoverIndex reset outside the conditional blocks if it should always happen when remote is true:
if (typeof props.filterMethod === 'function') {
props.filterMethod(value)
state.selectEmitter.emit(constants.COMPONENT_NAME.OptionGroup, constants.EVENT_NAME.queryChange)
// 如果同时存在 remoteMethod 且没有使用 panel 插槽,也调用 remoteMethod(兼容其他场景)
if (props.remote && typeof props.remoteMethod === 'function' && !vm.$slots?.panel) {
- state.hoverIndex = -1
props.remoteMethod(value, props.extraQueryParams)
}
} else if (props.remote && (typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function')) {
- state.hoverIndex = -1
props.remoteMethod && props.remoteMethod(value, props.extraQueryParams)
} else {
api.queryChange(value, isInput)
}
+if (props.remote && (typeof props.remoteMethod === 'function' || typeof props.filterMethod === 'function')) {
+ state.hoverIndex = -1
+}Also applies to: 80-80
🤖 Prompt for AI Agents
In packages/renderless/src/base-select/index.ts around lines 76 to 80, there is
a duplicated reset of state.hoverIndex = -1 inside both the new conditional
branch and its fallback; remove the redundant assignment and ensure the
hoverIndex reset runs exactly once (either move a single state.hoverIndex = -1
out of the conditional blocks to execute for the shared case, or keep it only in
the branch where it’s actually required), updating control flow so behavior
remains identical but the duplicate line is eliminated.
| :lazy="lazy !== undefined ? lazy : treeOp.lazy" | ||
| :load="load || treeOp.load" | ||
| :after-load="afterLoad || treeOp.afterLoad" | ||
| @check="check" | ||
| @node-click="nodeClick" | ||
| v-bind="treeOp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential prop override via v-bind="treeOp".
The explicit :lazy, :load, and :after-load bindings on lines 55-57 may be overridden by v-bind="treeOp" on line 60 if treeOp contains lazy, load, or afterLoad keys. In Vue, when both explicit bindings and v-bind are used, the order determines precedence—later attributes win.
Since v-bind="treeOp" comes after, the explicit bindings will be overridden. Consider moving v-bind="treeOp" before the explicit bindings, or destructuring treeOp to exclude these keys.
🔎 Suggested fix: Move v-bind before explicit bindings
<tiny-tree
ref="treeRef"
+ v-bind="treeOp"
:check-strictly="treeOp.checkStrictly"
:current-node-key="!multiple ? state.currentKey : ''"
:data="state.treeData"
:default-checked-keys="multiple ? state.defaultCheckedKeys : treeOp.defaultCheckedKeys || []"
:default-expand-all="
treeOp.defaultExpandAll !== undefined
? treeOp.defaultExpandAll
: (lazy !== undefined ? lazy : treeOp.lazy)
? false
: true
"
:expand-on-click-node="false"
:filter-node-method="filterMethod"
:icon-trigger-click-node="false"
:node-key="valueField"
:props="{ label: textField }"
:show-checkbox="multiple"
:lazy="lazy !== undefined ? lazy : treeOp.lazy"
:load="load || treeOp.load"
:after-load="afterLoad || treeOp.afterLoad"
@check="check"
@node-click="nodeClick"
- v-bind="treeOp"
></tiny-tree>Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/vue/src/tree-select/src/mobile-first.vue around lines 55 to 60,
v-bind="treeOp" is placed after explicit bindings for :lazy, :load and
:after-load so any corresponding keys in treeOp will override the explicit
props; to fix either move v-bind="treeOp" before those explicit bindings so the
explicit props take precedence, or filter/destructure treeOp to remove lazy,
load and afterLoad keys before binding (ensure attribute order or removal
prevents overrides).
| :lazy="lazy !== undefined ? lazy : treeOp.lazy" | ||
| :load="load || treeOp.load" | ||
| :after-load="afterLoad || treeOp.afterLoad" | ||
| @check="check" | ||
| @node-click="nodeClick" | ||
| v-bind="treeOp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same v-bind ordering issue as in mobile-first.vue.
The explicit :lazy, :load, and :after-load bindings on lines 34-36 may be overridden by v-bind="treeOp" on line 39. Consider moving v-bind="treeOp" before the explicit lazy-related bindings to ensure component-level props take precedence.
🔎 Suggested fix: Move v-bind before explicit bindings
<tiny-tree
ref="treeRef"
+ v-bind="treeOp"
:check-strictly="treeOp.checkStrictly"
:current-node-key="!multiple ? state.currentKey : ''"
:data="state.treeData"
:default-checked-keys="multiple ? state.defaultCheckedKeys : treeOp.defaultCheckedKeys || []"
:default-expand-all="treeOp.defaultExpandAll !== undefined ? treeOp.defaultExpandAll : ((lazy !== undefined ? lazy : treeOp.lazy) ? false : true)"
:expand-on-click-node="false"
:filter-node-method="filterMethod"
:icon-trigger-click-node="false"
:node-key="valueField"
:props="{ label: textField }"
:show-checkbox="multiple"
:lazy="lazy !== undefined ? lazy : treeOp.lazy"
:load="load || treeOp.load"
:after-load="afterLoad || treeOp.afterLoad"
@check="check"
@node-click="nodeClick"
- v-bind="treeOp"
></tiny-tree>Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/vue/src/tree-select/src/pc.vue around lines 34 to 39, the explicit
:lazy, :load and :after-load bindings are placed before v-bind="treeOp", so
treeOp can override them; move v-bind="treeOp" to appear before the explicit
lazy-related bindings (i.e., place v-bind="treeOp" on the element above
:lazy="..." :load="..." :after-load="...") so the explicit component-level props
take precedence; keep the event handlers (@check, @node-click) unchanged.
PR
feat:下拉树支持懒加载,
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
Release Notes
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.