diff --git a/.gitignore b/.gitignore index 47e893a7c..31f01c16e 100755 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ tests/test-case/dist # for my ai friends ai/meta/agent-guestbook.md +ai/meta/jisei.md # Numerous always-ignore extensions *.diff diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 438f2efcb..8df43a4dd 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -4,6 +4,15 @@ This is a pre-release version and APIs will change quickly. Before `1.0` release Please note after `1.0` Semver will be followed using normal protocols. +# Version 0.13.0 + +* **Query** - Added `clippingParent` to find closest ancestor which will clip the current element +* **Query** - `offsetParent` has been renamed to `containingParent` and now includes many other possible containing parent checks like `will-change` and `filter`. +* **Query** - `setting()` can now be used as a getter. +* **Query** - Added `.data()` for getting and setting html data +* **Query** - Added `.slice()` for returning a portion of the element collection +* **Query** - Fixed `offsetParent` to correctly return offset parent for willChange + # Version 0.12.4-1 * **Tailwind** - `@semantic-ui/tailwind` and `tailwindcss-iso` now have bundled CDN version to avoid issues importing css files in browser via esm. Modified `tailwind` package to accomodate this change. * **Tailwind** - Removed bundled `wasm` files, these are now part of the generic `tailwindcss-iso` package. diff --git a/ai/guides/html-css-style-guide.md b/ai/guides/html-css-style-guide.md index b1ea3b71b..c79cee9f3 100644 --- a/ai/guides/html-css-style-guide.md +++ b/ai/guides/html-css-style-guide.md @@ -1,6 +1,6 @@ # Semantic UI HTML & CSS Style Guide -Based on analysis of canonical examples authored by Jack Lukic, this guide captures the distinctive patterns and philosophies for writing HTML and CSS within Semantic UI web components. +This guide captures the distinctive patterns and philosophies for writing HTML and CSS within Semantic UI web components. ## Core Philosophy: Natural Language Applied to Markup @@ -467,4 +467,4 @@ Your HTML and CSS style reflects a sophisticated understanding of how natural la - **Smooth interactions** with design system transitions - **Seamless accessibility** integration -This approach creates code that leverages the full power of the design system while maintaining component-specific customization where needed. \ No newline at end of file +This approach creates code that leverages the full power of the design system while maintaining component-specific customization where needed. diff --git a/ai/specialized/query-system-guide.md b/ai/packages/query.md similarity index 75% rename from ai/specialized/query-system-guide.md rename to ai/packages/query.md index 612dc11c1..c11e59776 100644 --- a/ai/specialized/query-system-guide.md +++ b/ai/packages/query.md @@ -1,53 +1,78 @@ # Semantic UI Query System Guide -**For AI agents working with Semantic UI's `@semantic-ui/query` package** +> **For:** AI agents working with DOM querying and manipulation in Semantic UI +> **Purpose:** Comprehensive reference for the Query package and component debugging +> **Prerequisites:** Basic understanding of DOM and Shadow DOM concepts +> **Related:** [Mental Model](../foundations/mental-model.md) • [Component Guide](../guides/component-generation-instructions.md) • [Quick Reference](../foundations/quick-reference.md) +> **Back to:** [Documentation Hub](../00-START-HERE.md) -## Overview +--- -The `@semantic-ui/query` package is a standalone DOM querying and manipulation library that provides jQuery-like functionality with modern JavaScript features. It's designed specifically to handle Shadow DOM traversal and component-aware querying while remaining lightweight and focused. +## Table of Contents -## Package Structure +- [Core Query Concepts](#core-query-concepts) +- [Shadow DOM Traversal Strategy](#shadow-dom-traversal-strategy) +- [Component Instance Access](#component-instance-access) +- [Component Debugging Workflow](#component-debugging-workflow) +- [Event System Integration](#event-system-integration) +- [Performance Considerations](#performance-considerations) +- [Advanced Query Patterns](#advanced-query-patterns) +- [Troubleshooting Common Issues](#troubleshooting-common-issues) -``` -@semantic-ui/query -├── Query ← Main query class with DOM manipulation methods -├── $ function ← Standard DOM querying (respects Shadow DOM boundaries) -├── $$ function ← Deep querying (crosses Shadow DOM boundaries) -└── Utilities ← Global management and aliasing functions -``` +--- + +## Core Query Concepts + +### The Dual Query System + +Semantic UI provides two entry points for DOM querying, each with distinct capabilities: -**Main Exports**: ```javascript -import { $, $$, Query, exportGlobals, restoreGlobals, useAlias } from '@semantic-ui/query'; +import { $, $$ } from '@semantic-ui/query'; + +// Standard DOM querying (respects Shadow DOM boundaries) +$('button') // Finds buttons in light DOM only +$('ui-dropdown') // Finds dropdown components, but not their internal structure + +// Deep querying (pierces Shadow DOM boundaries) +$$('button') // Finds buttons in light AND shadow DOM +$$('ui-dropdown .item') // Finds .item elements inside dropdown's shadow DOM ``` -## Core Functions +**Mental Model**: Think of `$` as "CSS selectors" and `$$` as "CSS selectors that understand web components." + +### Query Instance Architecture -### $ - Standard DOM Querying +Every Query instance contains: -The `$` function provides standard DOM querying that respects Shadow DOM boundaries. +```javascript +const $elements = $('div'); + +// Core properties +$elements.length // Number of matched elements +$elements.selector // Original selector used +$elements.options // Query configuration (root, pierceShadow) +$elements[0], $elements[1] // Array-like access to elements + +// Chaining system +$elements.find('.child') // Returns new Query instance +$elements.chain([newEl]) // Create Query with specific elements +``` + +### Query Options and Configuration ```javascript -import { $ } from '@semantic-ui/query'; - -// Query selectors (standard CSS selectors) -$('.button') // All elements with class 'button' in light DOM -$('#main') // Element with id 'main' -$('input[type="text"]') // All text inputs -$('div > .child') // Direct child selectors - -// Create elements from HTML -$('
New content
'); -// Data attributes -$('.item').data('id', 123); -const itemId = $('.item').data('id'); +// HTML data attributes via attr() +$('.item').attr('data-id', '123'); +const itemId = $('.item').attr('data-id'); // Form values $('input[name="email"]').val('user@example.com'); diff --git a/ai/specialized/reactivity-system-guide.md b/ai/packages/reactivity.md similarity index 100% rename from ai/specialized/reactivity-system-guide.md rename to ai/packages/reactivity.md diff --git a/ai/specialized/templating-system-guide.md b/ai/packages/templating.md similarity index 100% rename from ai/specialized/templating-system-guide.md rename to ai/packages/templating.md diff --git a/ai/specialized/utils-package-guide.md b/ai/packages/utils.md similarity index 100% rename from ai/specialized/utils-package-guide.md rename to ai/packages/utils.md diff --git a/ai/proposals/animations.js b/ai/proposals/animations.js new file mode 100644 index 000000000..fc75a1dd5 --- /dev/null +++ b/ai/proposals/animations.js @@ -0,0 +1,287 @@ +/** + * Reusable keyframe objects. Stored as constants so they are defined only once + * and can be referenced by multiple animation definitions. This is ideal for + * both DRY principles and minification. + */ +const slideInY = { + '0%': { opacity: 0, transform: 'scaleY(0)' }, + '100%': { opacity: 1, transform: 'scaleY(1)' } +}; +const slideOutY = { + '0%': { opacity: 1, transform: 'scaleY(1)' }, + '100%': { opacity: 0, transform: 'scaleY(0)' } +}; +const slideInX = { + '0%': { opacity: 0, transform: 'scaleX(0)' }, + '100%': { opacity: 1, transform: 'scaleX(1)' } +}; +const slideOutX = { + '0%': { opacity: 1, transform: 'scaleX(1)' }, + '100%': { opacity: 0, transform: 'scaleX(0)' } +}; + +const swingInX = { + '0%': { transform: 'perspective(1000px) rotateX(90deg)', opacity: 0 }, + '40%': { transform: 'perspective(1000px) rotateX(-30deg)', opacity: 1 }, + '60%': { transform: 'perspective(1000px) rotateX(15deg)' }, + '80%': { transform: 'perspective(1000px) rotateX(-7.5deg)' }, + '100%': { transform: 'perspective(1000px) rotateX(0deg)' } +}; +const swingOutX = { + '0%': { transform: 'perspective(1000px) rotateX(0deg)' }, + '40%': { transform: 'perspective(1000px) rotateX(-7.5deg)' }, + '60%': { transform: 'perspective(1000px) rotateX(17.5deg)' }, + '80%': { transform: 'perspective(1000px) rotateX(-30deg)', opacity: 1 }, + '100%': { transform: 'perspective(1000px) rotateX(90deg)', opacity: 0 } +}; +const swingInY = { + '0%': { transform: 'perspective(1000px) rotateY(-90deg)', opacity: 0 }, + '40%': { transform: 'perspective(1000px) rotateY(30deg)', opacity: 1 }, + '60%': { transform: 'perspective(1000px) rotateY(-17.5deg)' }, + '80%': { transform: 'perspective(1000px) rotateY(7.5deg)' }, + '100%': { transform: 'perspective(1000px) rotateY(0deg)' } +}; +const swingOutY = { + '0%': { transform: 'perspective(1000px) rotateY(0deg)' }, + '40%': { transform: 'perspective(1000px) rotateY(7.5deg)' }, + '60%': { transform: 'perspective(1000px) rotateY(-10deg)' }, + '80%': { transform: 'perspective(1000px) rotateY(30deg)', opacity: 1 }, + '100%': { transform: 'perspective(1000px) rotateY(-90deg)', opacity: 0 } +}; + + +/** + * The main animation definitions, structured as JS objects for optimal minification. + * - `keyframe`: A direct reference to one of the reusable keyframe objects above. + * - `keyframeName`: A string to name the animation. This is used when the keyframe is unique. + * - `alias`: Points to another definition path within this object to avoid repetition. + */ +const animationDefinitions = { + browse: { + in: { + duration: '500ms', + keyframeName: 'browseIn', + keyframe: { + '0%': { transform: 'scale(0.8) translateZ(0px)', zIndex: -1 }, + '10%': { transform: 'scale(0.8) translateZ(0px)', zIndex: -1, opacity: 0.7 }, + '80%': { transform: 'scale(1.05) translateZ(0px)', opacity: 1, zIndex: 999 }, + '100%': { transform: 'scale(1) translateZ(0px)', zIndex: 999 } + } + }, + out: { + duration: '500ms', + keyframeName: 'browseOutLeft', + keyframe: { + '0%': { zIndex: 999, transform: 'translateX(0%) rotateY(0deg) rotateX(0deg)' }, + '50%': { zIndex: -1, transform: 'translateX(-105%) rotateY(35deg) rotateX(10deg) translateZ(-10px)' }, + '80%': { opacity: 1 }, + '100%': { zIndex: -1, transform: 'translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px)', opacity: 0 } + } + }, + right: { + out: { + duration: '500ms', + keyframeName: 'browseOutRight', + keyframe: { + '0%': { zIndex: 999, transform: 'translateX(0%) rotateY(0deg) rotateX(0deg)' }, + '50%': { zIndex: 1, transform: 'translateX(105%) rotateY(35deg) rotateX(10deg) translateZ(-10px)' }, + '80%': { opacity: 1 }, + '100%': { zIndex: 1, transform: 'translateX(0%) rotateY(0deg) rotateX(0deg) translateZ(-10px)', opacity: 0 } + } + } + } + }, + + drop: { + in: { + duration: '400ms', + keyframeName: 'dropIn', + keyframe: { + '0%': { opacity: 0, transform: 'scale(0)' }, + '100%': { opacity: 1, transform: 'scale(1)' } + } + }, + out: { + duration: '400ms', + keyframeName: 'dropOut', + keyframe: { + '0%': { opacity: 1, transform: 'scale(1)' }, + '100%': { opacity: 0, transform: 'scale(0)' } + } + } + }, + + fade: { + in: { duration: '300ms', keyframeName: 'fadeIn', keyframe: { '0%': { opacity: 0 }, '100%': { opacity: 1 } } }, + out: { duration: '300ms', keyframeName: 'fadeOut', keyframe: { '0%': { opacity: 1 }, '100%': { opacity: 0 } } }, + up: { + in: { keyframeName: 'fadeInUp', keyframe: { '0%': { opacity: 0, transform: 'translateY(10%)' }, '100%': { opacity: 1, transform: 'translateY(0%)' } } }, + out: { keyframeName: 'fadeOutUp', keyframe: { '0%': { opacity: 1, transform: 'translateY(0%)' }, '100%': { opacity: 0, transform: 'translateY(5%)' } } } + }, + down: { + in: { keyframeName: 'fadeInDown', keyframe: { '0%': { opacity: 0, transform: 'translateY(-10%)' }, '100%': { opacity: 1, transform: 'translateY(0%)' } } }, + out: { keyframeName: 'fadeOutDown', keyframe: { '0%': { opacity: 1, transform: 'translateY(0%)' }, '100%': { opacity: 0, transform: 'translateY(-5%)' } } } + }, + left: { + in: { keyframeName: 'fadeInLeft', keyframe: { '0%': { opacity: 0, transform: 'translateX(10%)' }, '100%': { opacity: 1, transform: 'translateX(0%)' } } }, + out: { keyframeName: 'fadeOutLeft', keyframe: { '0%': { opacity: 1, transform: 'translateX(0%)' }, '100%': { opacity: 0, transform: 'translateX(5%)' } } } + }, + right: { + in: { keyframeName: 'fadeInRight', keyframe: { '0%': { opacity: 0, transform: 'translateX(-10%)' }, '100%': { opacity: 1, transform: 'translateX(0%)' } } }, + out: { keyframeName: 'fadeOutRight', keyframe: { '0%': { opacity: 1, transform: 'translateX(0%)' }, '100%': { opacity: 0, transform: 'translateX(-5%)' } } } + } + }, + + fly: { + duration: '600ms', + in: { keyframeName: 'flyIn', keyframe: { '0%':{opacity:0,transform:'scale3d(.3,.3,.3)'},'20%':{transform:'scale3d(1.1,1.1,1.1)'},'40%':{transform:'scale3d(.9,.9,.9)'},'60%':{opacity:1,transform:'scale3d(1.03,1.03,1.03)'},'80%':{transform:'scale3d(.97,.97,.97)'},'100%':{opacity:1,transform:'scale3d(1,1,1)'} } }, + out: { keyframeName: 'flyOut', keyframe: { '20%':{transform:'scale3d(.9,.9,.9)'},'50%,55%':{opacity:1,transform:'scale3d(1.1,1.1,1.1)'},'100%':{opacity:0,transform:'scale3d(.3,.3,.3)'} } }, + up: { + in: { keyframeName: 'flyInUp', keyframe: { '0%':{opacity:0,transform:'translate3d(0,1500px,0)'},'60%':{opacity:1,transform:'translate3d(0,-20px,0)'},'75%':{transform:'translate3d(0,10px,0)'},'90%':{transform:'translate3d(0,-5px,0)'},'100%':{transform:'translate3d(0,0,0)'} } }, + out: { keyframeName: 'flyOutUp', keyframe: { '20%':{transform:'translate3d(0,10px,0)'},'40%,45%':{opacity:1,transform:'translate3d(0,-20px,0)'},'100%':{opacity:0,transform:'translate3d(0,2000px,0)'} } } + }, + down: { + in: { keyframeName: 'flyInDown', keyframe: { '0%':{opacity:0,transform:'translate3d(0,-1500px,0)'},'60%':{opacity:1,transform:'translate3d(0,25px,0)'},'75%':{transform:'translate3d(0,-10px,0)'},'90%':{transform:'translate3d(0,5px,0)'},'100%':{transform:'none'} } }, + out: { keyframeName: 'flyOutDown', keyframe: { '20%':{transform:'translate3d(0,-10px,0)'},'40%,45%':{opacity:1,transform:'translate3d(0,20px,0)'},'100%':{opacity:0,transform:'translate3d(0,-2000px,0)'} } } + }, + left: { + in: { keyframeName: 'flyInLeft', keyframe: { '0%':{opacity:0,transform:'translate3d(1500px,0,0)'},'60%':{opacity:1,transform:'translate3d(-25px,0,0)'},'75%':{transform:'translate3d(10px,0,0)'},'90%':{transform:'translate3d(-5px,0,0)'},'100%':{transform:'none'} } }, + out: { keyframeName: 'flyOutLeft', keyframe: { '20%':{opacity:1,transform:'translate3d(-20px,0,0)'},'100%':{opacity:0,transform:'translate3d(2000px,0,0)'} } } + }, + right: { + in: { keyframeName: 'flyInRight', keyframe: { '0%':{opacity:0,transform:'translate3d(-1500px,0,0)'},'60%':{opacity:1,transform:'translate3d(25px,0,0)'},'75%':{transform:'translate3d(-10px,0,0)'},'90%':{transform:'translate3d(5px,0,0)'},'100%':{transform:'none'} } }, + out: { keyframeName: 'flyOutRight', keyframe: { '20%':{opacity:1,transform:'translate3d(20px,0,0)'},'100%':{opacity:0,transform:'translate3d(-2000px,0,0)'} } } + } + }, + + flip: { + duration: '600ms', + horizontal: { + in: { keyframeName: 'horizontalFlipIn', keyframe: { '0%':{transform:'perspective(2000px) rotateY(-90deg)',opacity:0},'100%':{transform:'perspective(2000px) rotateY(0)',opacity:1} } }, + out: { keyframeName: 'horizontalFlipOut', keyframe: { '0%':{transform:'perspective(2000px) rotateY(0)',opacity:1},'100%':{transform:'perspective(2000px) rotateY(90deg)',opacity:0} } } + }, + vertical: { + in: { keyframeName: 'verticalFlipIn', keyframe: { '0%':{transform:'perspective(2000px) rotateX(-90deg)',opacity:0},'100%':{transform:'perspective(2000px) rotateX(0)',opacity:1} } }, + out: { keyframeName: 'verticalFlipOut', keyframe: { '0%':{transform:'perspective(2000px) rotateX(0)',opacity:1},'100%':{transform:'perspective(2000px) rotateX(-90deg)',opacity:0} } } + } + }, + + scale: { + in: { duration: '300ms', keyframeName: 'scaleIn', keyframe: { '0%': { opacity: 0, transform: 'scale(0.8)' }, '100%': { opacity: 1, transform: 'scale(1)' } } }, + out: { duration: '300ms', keyframeName: 'scaleOut', keyframe: { '0%': { opacity: 1, transform: 'scale(1)' }, '100%': { opacity: 0, transform: 'scale(0.9)' } } } + }, + + slide: { + down: { + in: { keyframeName: 'slideInY', keyframe: slideInY }, + out: { keyframeName: 'slideOutY', keyframe: slideOutY } + }, + up: { alias: 'slide.down' }, + left: { + in: { keyframeName: 'slideInX', keyframe: slideInX }, + out: { keyframeName: 'slideOutX', keyframe: slideOutX } + }, + right: { alias: 'slide.left' } + }, + + swing: { + duration: '800ms', + down: { + in: { keyframeName: 'swingInX', keyframe: swingInX }, + out: { keyframeName: 'swingOutX', keyframe: swingOutX } + }, + up: { alias: 'swing.down' }, + left: { + in: { keyframeName: 'swingInY', keyframe: swingInY }, + out: { keyframeName: 'swingOutY', keyframe: swingOutY } + }, + right: { alias: 'swing.left' } + }, + + zoom: { + in: { keyframeName: 'zoomIn', keyframe: { '0%':{opacity:1,transform:'scale(0)'},'100%':{opacity:1,transform:'scale(1)'} } }, + out: { keyframeName: 'zoomOut', keyframe: { '0%':{opacity:1,transform:'scale(1)'},'100%':{opacity:1,transform:'scale(0)'} } } + }, + + + // --- Static Animations (no in/out direction) --- + jiggle: { + static: { + duration: '750ms', + keyframeName: 'jiggle', + keyframe: { + '0%': { transform: 'scale3d(1, 1, 1)' }, + '30%': { transform: 'scale3d(1.25, 0.75, 1)' }, + '40%': { transform: 'scale3d(0.75, 1.25, 1)' }, + '50%': { transform: 'scale3d(1.15, 0.85, 1)' }, + '65%': { transform: 'scale3d(0.95, 1.05, 1)' }, + '75%': { transform: 'scale3d(1.05, 0.95, 1)' }, + '100%': { transform: 'scale3d(1, 1, 1)' } + } + } + }, + flash: { + static: { + duration: '750ms', + keyframeName: 'flash', + keyframe: { '0%, 50%, 100%': { opacity: 1 }, '25%, 75%': { opacity: 0 } } + } + }, + shake: { + static: { + duration: '750ms', + keyframeName: 'shake', + keyframe: { + '0%, 100%': { transform: 'translateX(0)' }, + '10%, 30%, 50%, 70%, 90%': { transform: 'translateX(-10px)' }, + '20%, 40%, 60%, 80%': { transform: 'translateX(10px)' } + } + } + }, + bounce: { + static: { + duration: '750ms', + keyframeName: 'bounce', + keyframe: { + '0%, 20%, 50%, 80%, 100%': { transform: 'translateY(0)' }, + '40%': { transform: 'translateY(-30px)' }, + '60%': { transform: 'translateY(-15px)' } + } + } + }, + tada: { + static: { + duration: '750ms', + keyframeName: 'tada', + keyframe: { + '0%': { transform: 'scale(1)' }, + '10%, 20%': { transform: 'scale(0.9) rotate(-3deg)' }, + '30%, 50%, 70%, 90%': { transform: 'scale(1.1) rotate(3deg)' }, + '40%, 60%, 80%': { transform: 'scale(1.1) rotate(-3deg)' }, + '100%': { transform: 'scale(1) rotate(0)' } + } + } + }, + pulse: { + static: { + duration: '500ms', + keyframeName: 'pulse', + keyframe: { + '0%': { transform: 'scale(1)', opacity: 1 }, + '50%': { transform: 'scale(0.9)', opacity: 0.7 }, + '100%': { transform: 'scale(1)', opacity: 1 } + } + } + }, + glow: { + static: { + duration: '2000ms', + keyframeName: 'glow', + keyframe: { + '0%': { backgroundColor: '#FCFCFD' }, + '30%': { backgroundColor: '#FFF6CD' }, + '100%': { backgroundColor: '#FCFCFD' } + } + } + } +}; diff --git a/ai/proposals/query-core-missing-methods.md b/ai/proposals/query-core-missing-methods.md new file mode 100644 index 000000000..301160984 --- /dev/null +++ b/ai/proposals/query-core-missing-methods.md @@ -0,0 +1,100 @@ +# Query Core - Missing Methods Proposal + +> **Scope:** Essential missing methods with minimal complexity +> **Status:** Draft for implementation +> **Size Impact:** Minimal - mostly aliases and simple logic reuse + +--- + +## Array-like Operations + +### `slice(start, end)` +Get subset of elements as new Query instance. + +- `start` - Number starting index +- `end` - Number ending index (optional) + +**Implementation:** Simple Array.slice() wrapper + +### `splice(start, deleteCount, ...items)` +Modify the element collection in place. + +- `start` - Number starting index +- `deleteCount` - Number of elements to remove +- `items` - Elements to insert at start position + +**Implementation:** Array.splice() with Query wrapping + +--- + +## Enhanced Traversal + +~~Enhanced traversal removed from core scope - `parents()` not commonly needed in practice~~ + +--- + +## DOM Insertion Aliases + +### `before(content)` +Alias for `insertBefore()` with more intuitive name. + +- `content` - String HTML | Element | Query | Array of content + +**Implementation:** Simple alias to existing insertBefore logic + +### `after(content)` +Alias for `insertAfter()` with more intuitive name. + +- `content` - String HTML | Element | Query | Array of content + +**Implementation:** Simple alias to existing insertAfter logic + +--- + +## Enhanced Dimensions + +### `width(options)` / `height(options)` +Extend existing methods with inclusion options. + +- `options.includeMargin` - Boolean to include margin +- `options.includePadding` - Boolean to include padding +- `options.includeBorder` - Boolean to include border + +**Implementation:** Extend existing width/height with computed style calculations + +--- + +## Data Attribute Helpers + +### `data(key, value)` +Get/set data-* attributes with type conversion. + +- `key` - String attribute name or Object of key-value pairs +- `value` - Any value to set, undefined to get + +**Implementation:** Wrapper around attr() with 'data-' prefix and JSON parsing + +### `data()` +Get all data-* attributes as object. + +**Implementation:** Filter attributes starting with 'data-', parse values + +--- + +## Shadow DOM Enhancements + +### `contains(selector)` +Check if elements contain targets. Automatically shadow DOM aware based on `this.options.pierceShadow`. + +- `selector` - String | Element | Query to check containment + +**Implementation:** Use DOM `.contains()` or deep traversal based on `this.options.pierceShadow` + +--- + +## Implementation Notes + +- **File size impact:** < 1.5KB gzipped +- **Complexity:** Very low - mostly aliases and simple extensions +- **Dependencies:** None - uses existing Query infrastructure +- **Breaking changes:** None - all additions \ No newline at end of file diff --git a/ai/proposals/query-css-animations.md b/ai/proposals/query-css-animations.md new file mode 100644 index 000000000..033f8ddb0 --- /dev/null +++ b/ai/proposals/query-css-animations.md @@ -0,0 +1,135 @@ +# Query CSS Animations Extension + +> **Scope:** CSS-based animations and transitions integration +> **Status:** Complex scope requiring design decisions +> **Size Impact:** Moderate - style injection and state management logic + +--- + +## Core Animation Methods + +### `show(options)` +Show elements with CSS animation support. + +- `options.animation` - String CSS animation class or transition property +- `options.duration` - String CSS duration ('300ms', '0.3s') +- `options.timing` - String CSS timing function ('ease', 'cubic-bezier(...)') +- `options.display` - String target display value ('block', 'flex', 'inline-block') + +### `hide(options)` +Hide elements with CSS animation support. + +- `options.animation` - String CSS animation class or transition property +- `options.duration` - String CSS duration +- `options.timing` - String CSS timing function + +### `toggle(force, options)` +Toggle visibility with animation support. + +- `force` - Boolean to force show/hide, undefined for toggle +- `options` - Same as show/hide options + +### `visible()` +Check if elements are visible. + +**Returns:** Boolean true if any element is visible + +--- + +## Design Challenges + +### Display State Resolution +**Problem:** When showing `display: none` elements, what should the final display value be? + +**Options:** +1. **Store original display** - Remember pre-hide display value +2. **Compute from CSS** - Analyze stylesheets for intended display +3. **Default + override** - Default to 'block', allow explicit override +4. **Element-based heuristics** - div=block, span=inline, etc. + +### Style Injection Strategy +**Problem:** How to inject temporary animation styles? + +**Options:** +1. **Inline styles** - Direct element.style modification +2. **Style sheet injection** - Dynamic ` + + +Simple testing environment for Semantic UI components.
+ +Loading components...
+