Compare commits

...

13 Commits

Author SHA1 Message Date
konnorrogers
de3eea6435 prettier 2026-01-15 13:36:03 -05:00
konnorrogers
da6d526887 fix broken tests 2026-01-15 13:34:38 -05:00
konnorrogers
8bf19a40d9 add comment 2026-01-15 13:29:00 -05:00
konnorrogers
9c34a5d4e3 prettier 2026-01-15 13:27:24 -05:00
konnorrogers
f7872a84b3 fix llms.js 2026-01-15 13:27:04 -05:00
konnorrogers
62b0bad271 prettier 2026-01-15 13:18:06 -05:00
konnorrogers
91080fb9ef fix if tag name doesn't exist 2026-01-15 13:17:55 -05:00
konnorrogers
405f762118 prettier 2026-01-15 13:14:33 -05:00
konnorrogers
a5c9ce3e92 update changelog 2026-01-15 13:14:12 -05:00
konnorrogers
0b541d71e8 composed path submenu fixes 2026-01-15 13:12:31 -05:00
konnorrogers
df86982d3d Merge branch 'next' of https://github.com/shoelace-style/webawesome into konnorrogers/composed-path-submenu 2026-01-15 13:07:51 -05:00
konnorrogers
7fecb5bcac Merge branch 'tkp/hf' of https://github.com/timkpaine/webawesome into konnorrogers/composed-path-submenu 2026-01-15 13:07:34 -05:00
Tim Paine
01d528c5a6 Search event composed path for submenu item 2025-12-12 15:04:31 -05:00
9 changed files with 77 additions and 35 deletions

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@ yarn.lock
_bundle_
/packages/webawesome-pro
/packages/webawesome-app
custom-elements.json

19
package-lock.json generated
View File

@@ -1880,6 +1880,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
"license": "MIT"
},
"node_modules/@lit-labs/eleventy-plugin-lit": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@lit-labs/eleventy-plugin-lit/-/eleventy-plugin-lit-1.0.5.tgz",
@@ -5420,6 +5426,18 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"node_modules/chart.js": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz",
"integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -14646,6 +14664,7 @@
"@lit/react": "^1.0.8",
"@shoelace-style/animations": "^1.2.0",
"@shoelace-style/localize": "^3.2.1",
"chart.js": "^4.5.1",
"composed-offset-position": "^0.0.6",
"lit": "^3.2.1",
"nanoid": "^5.1.5",

View File

@@ -1,18 +1,18 @@
import { cemInheritancePlugin } from '@wc-toolkit/cem-inheritance';
import { cemValidatorPlugin } from '@wc-toolkit/cem-validator';
import { jsxTypesPlugin } from '@wc-toolkit/jsx-types';
import { getTsProgram, typeParserPlugin } from '@wc-toolkit/type-parser';
import { parse } from 'comment-parser';
import { customElementJetBrainsPlugin } from 'custom-element-jet-brains-integration';
import { customElementSveltePlugin } from 'custom-element-svelte-integration';
import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
import { customElementVuejsPlugin } from 'custom-element-vuejs-integration';
import { parse } from 'comment-parser';
import fs from 'fs';
import * as path from 'node:path';
import { pascalCase } from 'pascal-case';
import * as url from 'url';
import { llmsTxtPlugin } from './scripts/llms.js';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
import { getTsProgram, typeParserPlugin } from "@wc-toolkit/type-parser";
import { cemValidatorPlugin } from "@wc-toolkit/cem-validator";
import { cemInheritancePlugin } from "@wc-toolkit/cem-inheritance";
import { customElementSveltePlugin } from "custom-element-svelte-integration";
const packageData = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
const { name, description, version, author, homepage, license } = packageData;
@@ -34,11 +34,9 @@ export default {
dependencies: true,
outdir,
// Give the plugin access to the TypeScript type checker
overrideModuleCreation({ts, globs}) {
const program = getTsProgram(ts, globs, "tsconfig.json");
return program
.getSourceFiles()
.filter((sf) => globs.find((glob) => sf.fileName.includes(glob)));
overrideModuleCreation({ ts, globs }) {
const program = getTsProgram(ts, globs, 'tsconfig.json');
return program.getSourceFiles().filter(sf => globs.find(glob => sf.fileName.includes(glob)));
},
plugins: [
@@ -52,7 +50,7 @@ export default {
},
cemInheritancePlugin({
fileName: "custom-elements.json",
fileName: 'custom-elements.json',
outdir,
}),
@@ -220,11 +218,11 @@ export default {
customElementVuejsPlugin({
outdir: './dist-cdn/types/vue',
fileName: 'index.d.ts',
componentTypePath: (_, tag) => `../../components/${tag.replace('wa-', '')}/${tag.replace('wa-', '')}.js`
componentTypePath: (_, tag) => `../../components/${tag.replace('wa-', '')}/${tag.replace('wa-', '')}.js`,
}),
customElementSveltePlugin({
outdir: "./dist-cdn/types/svelte",
fileName: "index.d.ts"
outdir: './dist-cdn/types/svelte',
fileName: 'index.d.ts',
}),
// cemValidatorPlugin({
// cemFileName: "./dist-cdn/custom-elements.json"

View File

@@ -11,7 +11,7 @@ export function getComponents() {
const manifest = JSON.parse(readFileSync(join(distDir, 'custom-elements.json'), 'utf-8'));
const components = [];
const sortByName = (a, b) => (a.name || "").localeCompare(b.name || "")
const sortByName = (a, b) => (a.name || '').localeCompare(b.name || '');
manifest.modules?.forEach(module => {
module.declarations?.forEach(declaration => {
if (declaration.customElement) {
@@ -19,15 +19,15 @@ export function getComponents() {
declaration.path = module.path.replace(/^src\//, 'dist/').replace(/\.ts$/, '.js');
// Remove private members and those that lack a description
const slots = declaration.slots?.sort(sortByName)
const events = declaration.events?.sort(sortByName)
const cssProperties = declaration.cssProperties?.sort(sortByName)
const cssParts = declaration.cssParts?.sort(sortByName)
const cssStates = declaration.cssStates?.sort(sortByName)
const dependencies = declaration.dependencies?.sort((a, b) => a.localeCompare(b))
const slots = declaration.slots?.sort(sortByName);
const events = declaration.events?.sort(sortByName);
const cssProperties = declaration.cssProperties?.sort(sortByName);
const cssParts = declaration.cssParts?.sort(sortByName);
const cssStates = declaration.cssStates?.sort(sortByName);
const dependencies = declaration.dependencies?.sort((a, b) => a.localeCompare(b));
const members = declaration.members?.filter(member => member.description && member.privacy !== 'private')
const members = declaration.members
?.filter(member => member.description && member.privacy !== 'private')
?.sort(sortByName);
const methods = members?.filter(prop => prop.kind === 'method' && prop.privacy !== 'private');
const properties = members?.filter(prop => {
@@ -38,7 +38,7 @@ export function getComponents() {
}
return prop.kind === 'field' && prop.privacy !== 'private';
})
});
components.push({
...declaration,
slots,

View File

@@ -21,9 +21,10 @@ Components with the <wa-badge variant="warning">Experimental</wa-badge> badge sh
- Added `wa-justify-content-*` utility classes [pr:1930]
- Added missing `wa-gap-4xl` utility class [pr:1931]
- Added `track` and `indicator` CSS parts to `<wa-progress-ring>` [pr:1863]
- [Docs]: component APIs like slots, state, methods, etc, are now alphabetized [pr:]
- [Docs]: component APIs now properly check their inheritance chain [pr:]
- [Docs]: Included framework specific documentation for Svelte, Vue, and Angular. [pr:]
- [Docs]: component APIs like slots, state, methods, etc, are now alphabetized [pr:1895]
- [Docs]: component APIs now properly check their inheritance chain [pr:1895]
- [Docs]: Included framework specific documentation for Svelte, Vue, and Angular. [pr:1895]
- Fixed a bug in `<wa-dropdown>` where submenu detection would not work in shadow dom. [pr:]
- Fixed a bug in `<wa-combobox>` that prevented the listbox from opening when options were preselected [issue:1883]
- Fixed a bug in `<wa-combobox>` that prevented the listbox from opening when options were preselected [issue:1883]
- Fixed a bug in `<wa-popup>` and `<wa-dropdown-item>` that caused an error when removing a popup while it was opening [issue:1910]
@@ -541,4 +542,4 @@ Many of these changes and improvements were the direct result of feedback from u
</details>
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions)
Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions)

View File

@@ -16,6 +16,10 @@ function loadAllFrontMatter(components, docsDir) {
const cache = new Map();
for (const component of components) {
if (!component.tagName) {
continue;
}
const componentName = component.tagName.replace(/^wa-/, '');
const mdPath = path.join(docsDir, 'docs/components', `${componentName}.md`);
@@ -36,6 +40,11 @@ function loadAllFrontMatter(components, docsDir) {
/** Generates the API reference section for a single component. */
function generateComponentApiSection(component, frontMatterCache, baseUrl) {
const lines = [];
if (!component.tagName) {
return lines;
}
const frontMatter = frontMatterCache.get(component.tagName);
const componentSlug = component.tagName.replace(/^wa-/, '');
const description = removeNewlines(frontMatter?.description || component.summary || '');
@@ -144,6 +153,8 @@ function generateComponentApiSection(component, frontMatterCache, baseUrl) {
* Generates the complete llms.txt content.
*/
function generateLlmsTxt({ components, packageData, frontMatterCache, baseUrl }) {
// Account for base "abstract elements" that don't have a tagName.
components = components.filter(c => c.tagName);
const lines = [];
// H1 Title (required by llmstxt.org spec)

View File

@@ -22,7 +22,9 @@ const components = getAllComponents(metadata);
const index = [];
for await (const component of components) {
if (!component.tagName) { continue }
if (!component.tagName) {
continue;
}
const tagWithoutPrefix = component.tagName.replace(/^wa-/, '');
const componentDir = path.join(reactDir, tagWithoutPrefix);
const componentFile = path.join(componentDir, 'index.ts');

View File

@@ -661,16 +661,22 @@ export default class WaDropdown extends WebAwesomeElement {
currentSubmenuItem.submenuElement.style.setProperty('--safe-triangle-cursor-x', `${constrainedX}px`);
currentSubmenuItem.submenuElement.style.setProperty('--safe-triangle-cursor-y', `${constrainedY}px`);
const isOverItem = currentSubmenuItem.matches(':hover');
// Calculate these up front since this event cant fire a lot.
const composedPath = event.composedPath();
const submenuItemHovered = currentSubmenuItem.matches(':hover');
const submenuElementHovered = Boolean(currentSubmenuItem.submenuElement?.matches(':hover'));
const isOverItem = submenuItemHovered || !!composedPath.find(el => el === currentSubmenuItem);
const isOverSubmenu =
currentSubmenuItem.submenuElement?.matches(':hover') ||
!!event
.composedPath()
.find(el => el instanceof HTMLElement && el.closest('[part="submenu"]') === currentSubmenuItem.submenuElement);
submenuElementHovered ||
!!composedPath.find(
el => el instanceof HTMLElement && el.closest('[part="submenu"]') === currentSubmenuItem.submenuElement,
);
if (!isOverItem && !isOverSubmenu) {
setTimeout(() => {
if (!currentSubmenuItem.matches(':hover') && !currentSubmenuItem.submenuElement?.matches(':hover')) {
if (!submenuItemHovered && !submenuElementHovered) {
currentSubmenuItem.submenuOpen = false;
}
}, 100);

View File

@@ -11,6 +11,10 @@ const metadata = JSON.parse(readFileSync('./dist/custom-elements.json'), 'utf8')
const serverComponents = [];
const componentImports = [];
getAllComponents(metadata).forEach(component => {
if (!component.tagName) {
return;
}
const name = component.tagName.replace(/^wa-/, '');
serverComponents.push(`/dist/components/${name}/${name}.js`);