@sprlab/wccompiler 0.10.11 → 0.10.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -65
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -695,38 +695,20 @@ Each standalone component has its own isolated reactive runtime. Signals from co
|
|
|
695
695
|
|
|
696
696
|
## Framework Integrations
|
|
697
697
|
|
|
698
|
-
WCC components are native custom elements — they work in any framework. Props, events, and named slots work natively with zero WCC-specific config. Two-way binding is zero-config in Angular; Vue
|
|
698
|
+
WCC components are native custom elements — they work in any framework. Props, events, and named slots work natively with zero WCC-specific config. Two-way binding is zero-config in Angular; Vue requires a plugin. Scoped slots require a framework plugin or directive for idiomatic syntax.
|
|
699
699
|
|
|
700
|
-
###
|
|
700
|
+
### Feature Support Matrix
|
|
701
701
|
|
|
702
|
-
|
|
702
|
+
| Feature | Vue (plugin) | Angular (directive) | React 19 (plugin) |
|
|
703
|
+
|---------|--------------|--------------------|--------------------|
|
|
704
|
+
| Props | ✅ `:count="ref"` | ✅ `[count]="signal()"` | ✅ `count={state}` |
|
|
705
|
+
| Events | ✅ `@count-changed="handler($event.detail)"` | ✅ `(count-changed)="handler($event.detail)"` | ✅ `oncountchanged={(e) => handler(e.detail)}` |
|
|
706
|
+
| Two-way binding | ✅ `v-model:count="ref"` | ✅ `[(count)]="signal"` | ❌ Not applicable |
|
|
707
|
+
| Default slot | ✅ children | ✅ children | ✅ children |
|
|
708
|
+
| Named slots | ✅ `<template #name>` | ✅ `<div slot-name>` | ✅ `<WccCard.Header>` |
|
|
709
|
+
| Scoped slots | ✅ `<template #name="{ prop }">` | ✅ `<ng-template slot="name" let-prop>` | ✅ `<WccList.Item>{(prop) => jsx}</WccList.Item>` |
|
|
703
710
|
|
|
704
|
-
|
|
705
|
-
<script type="module" src="dist/wcc-counter.js"></script>
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
**Vue:**
|
|
709
|
-
```vue
|
|
710
|
-
<wcc-counter :count="ref" @count-changed="handler($event.detail)">
|
|
711
|
-
<div slot="footer">Footer content</div>
|
|
712
|
-
</wcc-counter>
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
**React 19:**
|
|
716
|
-
```jsx
|
|
717
|
-
<wcc-counter count={state} onCountchanged={(e) => handler(e.detail)}>
|
|
718
|
-
<div slot="footer">Footer content</div>
|
|
719
|
-
</wcc-counter>
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
**Angular:**
|
|
723
|
-
```html
|
|
724
|
-
<wcc-counter [count]="signal()" (count-changed)="handler($event.detail)" [(count)]="signal">
|
|
725
|
-
<div slot="footer">Footer content</div>
|
|
726
|
-
</wcc-counter>
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
### Vue Plugin (v-model, modifiers, scoped slots)
|
|
711
|
+
### Vue (with `wccVuePlugin`)
|
|
730
712
|
|
|
731
713
|
```js
|
|
732
714
|
// vite.config.js
|
|
@@ -735,65 +717,184 @@ export default defineConfig({ plugins: [wccVuePlugin()] })
|
|
|
735
717
|
```
|
|
736
718
|
|
|
737
719
|
```vue
|
|
738
|
-
<
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
</
|
|
743
|
-
```
|
|
744
|
-
|
|
745
|
-
The plugin is needed for: v-model:prop (Vue assigns raw Event, not detail), v-model modifiers (.trim, .number), and scoped slot syntax (`{{prop}}` → `{%prop%}` escape).
|
|
746
|
-
|
|
747
|
-
Without the plugin, use `:prop` + `@prop-changed` for two-way binding manually.
|
|
748
|
-
|
|
749
|
-
### React Plugin + Wrappers (scoped slots, typed events, two-way)
|
|
750
|
-
|
|
751
|
-
```js
|
|
752
|
-
// vite.config.js
|
|
753
|
-
import { wccReactPlugin } from '@sprlab/wccompiler/integrations/react'
|
|
754
|
-
import react from '@vitejs/plugin-react'
|
|
755
|
-
export default defineConfig({ plugins: [wccReactPlugin(), react()] })
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
```jsx
|
|
759
|
-
// Auto-generated wrappers — events unwrapped, React-idiomatic naming
|
|
760
|
-
import { createWccWrappers } from '@sprlab/wccompiler/adapters/react'
|
|
761
|
-
const { WccCounter, WccCard } = createWccWrappers()
|
|
720
|
+
<script setup>
|
|
721
|
+
import { ref } from 'vue'
|
|
722
|
+
const count = ref(0)
|
|
723
|
+
const text = ref('')
|
|
724
|
+
</script>
|
|
762
725
|
|
|
763
|
-
<
|
|
764
|
-
|
|
765
|
-
<
|
|
766
|
-
|
|
726
|
+
<template>
|
|
727
|
+
<!-- Props -->
|
|
728
|
+
<wcc-counter :count="count" label="Clicks"></wcc-counter>
|
|
729
|
+
|
|
730
|
+
<!-- Events -->
|
|
731
|
+
<wcc-counter @count-changed="count = $event.detail"></wcc-counter>
|
|
732
|
+
|
|
733
|
+
<!-- Two-way binding (v-model) -->
|
|
734
|
+
<wcc-counter v-model:count="count"></wcc-counter>
|
|
735
|
+
<wcc-input v-model.trim="text"></wcc-input>
|
|
736
|
+
|
|
737
|
+
<!-- Default slot -->
|
|
738
|
+
<wcc-card>
|
|
739
|
+
<p>Body content</p>
|
|
740
|
+
</wcc-card>
|
|
741
|
+
|
|
742
|
+
<!-- Named slots -->
|
|
743
|
+
<wcc-card>
|
|
744
|
+
<template #header><strong>Title</strong></template>
|
|
745
|
+
<p>Body</p>
|
|
746
|
+
<template #footer>Footer text</template>
|
|
747
|
+
</wcc-card>
|
|
748
|
+
|
|
749
|
+
<!-- Scoped slots -->
|
|
750
|
+
<wcc-list>
|
|
751
|
+
<template #item="{ item, index }">
|
|
752
|
+
<li>{{ index }}: {{ item }}</li>
|
|
753
|
+
</template>
|
|
754
|
+
</wcc-list>
|
|
755
|
+
</template>
|
|
767
756
|
```
|
|
768
757
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
### Angular Directive (scoped slots only)
|
|
758
|
+
The plugin provides: `isCustomElement` config, `v-model:prop` support, v-model modifiers (`.trim`, `.number`), and scoped slot syntax (`{{prop}}` → `{%prop%}` escape).
|
|
772
759
|
|
|
773
|
-
Angular
|
|
760
|
+
### Angular (with `WccSlotsDirective`)
|
|
774
761
|
|
|
775
762
|
```ts
|
|
763
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
|
|
776
764
|
import { WccSlotsDirective, WccSlotDef } from '@sprlab/wccompiler/adapters/angular'
|
|
777
765
|
|
|
778
766
|
@Component({
|
|
779
767
|
imports: [WccSlotsDirective, WccSlotDef],
|
|
780
768
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
781
769
|
template: `
|
|
770
|
+
<!-- Props -->
|
|
771
|
+
<wcc-counter [count]="count" label="Clicks"></wcc-counter>
|
|
772
|
+
|
|
773
|
+
<!-- Events -->
|
|
774
|
+
<wcc-counter (count-changed)="onCount($event.detail)"></wcc-counter>
|
|
775
|
+
|
|
776
|
+
<!-- Two-way binding (banana-box) -->
|
|
777
|
+
<wcc-counter [(count)]="count"></wcc-counter>
|
|
778
|
+
|
|
779
|
+
<!-- Default slot -->
|
|
780
|
+
<wcc-card>
|
|
781
|
+
<p>Body content</p>
|
|
782
|
+
</wcc-card>
|
|
783
|
+
|
|
784
|
+
<!-- Named slots -->
|
|
782
785
|
<wcc-card wccSlots>
|
|
783
|
-
<
|
|
784
|
-
<
|
|
786
|
+
<strong slot-header>Title</strong>
|
|
787
|
+
<p>Body</p>
|
|
788
|
+
<span slot-footer>Footer text</span>
|
|
785
789
|
</wcc-card>
|
|
790
|
+
|
|
791
|
+
<!-- Scoped slots -->
|
|
792
|
+
<wcc-list wccSlots>
|
|
793
|
+
<ng-template slot="item" let-item let-index="index">
|
|
794
|
+
<li>{{ index }}: {{ item }}</li>
|
|
795
|
+
</ng-template>
|
|
796
|
+
</wcc-list>
|
|
786
797
|
`
|
|
787
798
|
})
|
|
799
|
+
export class AppComponent {
|
|
800
|
+
count = 0
|
|
801
|
+
onCount(value: number) { this.count = value }
|
|
802
|
+
}
|
|
788
803
|
```
|
|
789
804
|
|
|
790
|
-
|
|
805
|
+
Angular needs no plugin for props, events, or two-way binding — only `CUSTOM_ELEMENTS_SCHEMA`. The directive is only needed for named slots (with `slot-name` syntax) and scoped slots.
|
|
806
|
+
|
|
807
|
+
### React 19 (with `wccReactPlugin`)
|
|
808
|
+
|
|
809
|
+
```js
|
|
810
|
+
// vite.config.js
|
|
811
|
+
import { wccReactPlugin } from '@sprlab/wccompiler/integrations/react'
|
|
812
|
+
import react from '@vitejs/plugin-react'
|
|
813
|
+
export default defineConfig({ plugins: [wccReactPlugin({ prefix: 'wcc-' }), react()] })
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
```jsx
|
|
817
|
+
import { useState } from 'react'
|
|
818
|
+
import { WccCard, WccList } from './dist/wcc-react'
|
|
819
|
+
|
|
820
|
+
export default function App() {
|
|
821
|
+
const [count, setCount] = useState(0)
|
|
822
|
+
|
|
823
|
+
return (
|
|
824
|
+
<>
|
|
825
|
+
{/* Props */}
|
|
826
|
+
<wcc-counter count={count} label="Clicks"></wcc-counter>
|
|
827
|
+
|
|
828
|
+
{/* Events */}
|
|
829
|
+
<wcc-counter oncountchanged={(e) => setCount(e.detail)}></wcc-counter>
|
|
830
|
+
|
|
831
|
+
{/* Default slot */}
|
|
832
|
+
<WccCard>
|
|
833
|
+
<p>Body content</p>
|
|
834
|
+
</WccCard>
|
|
835
|
+
|
|
836
|
+
{/* Named slots (compound pattern) */}
|
|
837
|
+
<WccCard>
|
|
838
|
+
<WccCard.Header><strong>Title</strong></WccCard.Header>
|
|
839
|
+
<p>Body</p>
|
|
840
|
+
<WccCard.Footer>Footer text</WccCard.Footer>
|
|
841
|
+
</WccCard>
|
|
842
|
+
|
|
843
|
+
{/* Named slots (props pattern) */}
|
|
844
|
+
<wcc-card header={<strong>Title</strong>} footer="Footer text">
|
|
845
|
+
<p>Body</p>
|
|
846
|
+
</wcc-card>
|
|
847
|
+
|
|
848
|
+
{/* Scoped slots (compound pattern) */}
|
|
849
|
+
<WccList>
|
|
850
|
+
<WccList.Item>{(item, index) => <li>{index}: {item}</li>}</WccList.Item>
|
|
851
|
+
</WccList>
|
|
852
|
+
|
|
853
|
+
{/* Scoped slots (render prop pattern) */}
|
|
854
|
+
<wcc-list renderItem={(item, index) => <li>{index}: {item}</li>} />
|
|
855
|
+
</>
|
|
856
|
+
)
|
|
857
|
+
}
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
The plugin transforms PascalCase tags, compound components, props-as-slots, and render props at build time. Import stubs from `./dist/wcc-react` (auto-generated by `wcc build`).
|
|
861
|
+
|
|
862
|
+
### Vanilla (no framework)
|
|
791
863
|
|
|
792
864
|
No configuration needed:
|
|
793
865
|
|
|
794
866
|
```html
|
|
795
867
|
<script type="module" src="dist/wcc-counter.js"></script>
|
|
796
|
-
<wcc-
|
|
868
|
+
<script type="module" src="dist/wcc-card.js"></script>
|
|
869
|
+
<script type="module" src="dist/wcc-list.js"></script>
|
|
870
|
+
|
|
871
|
+
<!-- Props (attributes) -->
|
|
872
|
+
<wcc-counter count="0" label="Clicks"></wcc-counter>
|
|
873
|
+
|
|
874
|
+
<!-- Events -->
|
|
875
|
+
<script>
|
|
876
|
+
document.querySelector('wcc-counter')
|
|
877
|
+
.addEventListener('count-changed', (e) => console.log(e.detail))
|
|
878
|
+
</script>
|
|
879
|
+
|
|
880
|
+
<!-- Default slot -->
|
|
881
|
+
<wcc-card>
|
|
882
|
+
<p>Body content</p>
|
|
883
|
+
</wcc-card>
|
|
884
|
+
|
|
885
|
+
<!-- Named slots -->
|
|
886
|
+
<wcc-card>
|
|
887
|
+
<strong slot="header">Title</strong>
|
|
888
|
+
<p>Body</p>
|
|
889
|
+
<span slot="footer">Footer text</span>
|
|
890
|
+
</wcc-card>
|
|
891
|
+
|
|
892
|
+
<!-- Scoped slots -->
|
|
893
|
+
<wcc-list>
|
|
894
|
+
<template #item="{ item, index }">
|
|
895
|
+
<li>{{index}}: {{item}}</li>
|
|
896
|
+
</template>
|
|
897
|
+
</wcc-list>
|
|
797
898
|
```
|
|
798
899
|
|
|
799
900
|
## Editor Support
|
package/package.json
CHANGED