@vue-lynx-example/css-features 0.2.2 → 0.2.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-lynx-example/css-features",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "private": false,
5
5
  "description": "Vue-Lynx CSS features demo — scoped, modules, v-bind()",
6
6
  "license": "Apache-2.0",
@@ -17,7 +17,7 @@
17
17
  "directory": "examples/css-features"
18
18
  },
19
19
  "dependencies": {
20
- "vue-lynx": "0.2.0"
20
+ "vue-lynx": "0.3.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@lynx-js/rspeedy": "^0.13.5",
package/src/App.vue CHANGED
@@ -3,6 +3,7 @@ import PlainStyle from './PlainStyle.vue'
3
3
  import ScopedStyle from './ScopedStyle.vue'
4
4
  import CSSModules from './CSSModules.vue'
5
5
  import VBindCSS from './VBindCSS.vue'
6
+ import VBindThreads from './VBindThreads.vue'
6
7
  import CSSVarsWorkaround from './CSSVarsWorkaround.vue'
7
8
  import ImportedCSS from './ImportedCSS.vue'
8
9
  </script>
@@ -19,15 +20,18 @@ import ImportedCSS from './ImportedCSS.vue'
19
20
  <!-- 1. Plain <style> — WORKS -->
20
21
  <PlainStyle />
21
22
 
22
- <!-- 2. <style scoped> — DOES NOT WORK -->
23
+ <!-- 2a. <style scoped> — DOES NOT WORK -->
23
24
  <ScopedStyle />
24
25
 
25
26
  <!-- 3. <style module> — SHOULD WORK -->
26
27
  <CSSModules />
27
28
 
28
- <!-- 4. v-bind() in CSS — DOES NOT WORK -->
29
+ <!-- 4. v-bind() in CSS — WORKS (useCssVars implemented in vue-lynx) -->
29
30
  <VBindCSS />
30
31
 
32
+ <!-- 4b. v-bind() thread comparison — BG (useCssVars) vs MT (setStyleProperty) -->
33
+ <VBindThreads />
34
+
31
35
  <!-- 5. Workaround: Reactive inline :style -->
32
36
  <CSSVarsWorkaround />
33
37
 
package/src/VBindCSS.vue CHANGED
@@ -1,44 +1,166 @@
1
1
  <script setup lang="ts">
2
- // Test: v-bind() in <style>
3
- //
4
- // RESULT: BUILD ERROR — confirmed.
5
- //
6
- // Vue's v-bind() in CSS compiles to a `useCssVars()` call, which is a
7
- // @vue/runtime-dom API (not runtime-core). vue-lynx only re-exports from
8
- // @vue/runtime-core, so this API is unavailable.
9
- //
10
- // Error message:
11
- // ESModulesLinkingError: export 'useCssVars' (imported as '_useCssVars')
12
- // was not found in 'vue'
13
- //
14
- // Even if useCssVars were exported, it would not work because:
15
- // 1. useCssVars internally calls `document.getElementById()` — no document in Lynx
16
- // 2. It sets CSS vars via `el.style.setProperty()` — DOM API, not available
17
- // 3. The Background Thread cannot directly access native element styles
18
- //
19
- // WORKAROUND: Use computed() + reactive :style bindings instead.
20
- // See CSSVarsWorkaround.vue for the recommended pattern.
2
+ import { ref, computed } from 'vue'
3
+
4
+ const textColor = ref('#1565c0')
5
+ const bgColor = ref('#e3f2fd')
6
+ const fontSize = ref('14px')
7
+ const opacity = ref(1)
8
+ const borderStyle = ref({ color: '#1565c0' })
9
+
10
+ const invertedColor = computed(() => {
11
+ const map: Record<string, string> = {
12
+ '#1565c0': '#f57f17',
13
+ '#c62828': '#2e7d32',
14
+ '#2e7d32': '#c62828',
15
+ '#f57f17': '#1565c0',
16
+ }
17
+ return map[textColor.value] ?? textColor.value
18
+ })
19
+
20
+ function cycleColor() {
21
+ const colors = ['#1565c0', '#c62828', '#2e7d32', '#f57f17']
22
+ const idx = colors.indexOf(textColor.value)
23
+ textColor.value = colors[(idx + 1) % colors.length]
24
+ const bgs = ['#e3f2fd', '#ffebee', '#e8f5e9', '#fffde7']
25
+ bgColor.value = bgs[(idx + 1) % bgs.length]
26
+ borderStyle.value = { color: colors[(idx + 1) % colors.length] }
27
+ }
28
+
29
+ function cycleFontSize() {
30
+ const sizes = ['12px', '14px', '16px', '20px']
31
+ const idx = sizes.indexOf(fontSize.value)
32
+ fontSize.value = sizes[(idx + 1) % sizes.length]
33
+ }
34
+
35
+ function cycleOpacity() {
36
+ const steps = [1, 0.7, 0.4, 0.1]
37
+ const idx = steps.indexOf(opacity.value)
38
+ opacity.value = steps[(idx + 1) % steps.length]
39
+ }
21
40
  </script>
22
41
 
23
42
  <template>
24
43
  <view :style="{
25
44
  display: 'flex',
26
45
  flexDirection: 'column',
27
- backgroundColor: '#ffebee',
46
+ backgroundColor: bgColor,
28
47
  padding: '12px',
29
48
  borderRadius: '8px',
30
49
  marginBottom: '12px',
31
50
  }">
32
- <text :style="{ fontSize: '15px', fontWeight: 'bold', color: '#c62828', marginBottom: '4px' }">
33
- v-bind() in &lt;style&gt; — BUILD ERROR
51
+ <text :style="{ fontSize: '15px', fontWeight: 'bold', marginBottom: '4px' }" class="title">
52
+ v-bind() in &lt;style&gt; — WORKS
53
+ </text>
54
+ <text class="description">
55
+ textColor: {{ textColor }} | fontSize: {{ fontSize }} | opacity: {{ opacity }}
56
+ </text>
57
+
58
+ <!-- ref binding -->
59
+ <text class="sample-text" :style="{ fontSize }">
60
+ ref — color: v-bind(textColor)
61
+ </text>
62
+
63
+ <!-- computed binding -->
64
+ <text class="computed-text" :style="{ fontSize }">
65
+ computed — inverted color
66
+ </text>
67
+
68
+ <!-- object property binding: v-bind('obj.prop') -->
69
+ <text class="border-text">
70
+ object prop — v-bind('borderStyle.color')
34
71
  </text>
35
- <text :style="{ fontSize: '12px', color: '#555', marginBottom: '8px' }">
36
- Vue's v-bind() in CSS compiles to useCssVars() which is a
37
- @vue/runtime-dom API. vue-lynx only uses @vue/runtime-core,
38
- so this causes an ESModulesLinkingError at build time.
72
+
73
+ <!-- opacity binding -->
74
+ <text class="opacity-text">
75
+ opacity v-bind(opacity)
39
76
  </text>
40
- <text :style="{ fontSize: '11px', color: '#888', fontStyle: 'italic' }">
41
- Workaround: use computed() + :style bindings (see below)
77
+
78
+ <!-- CSS custom property via v-bind -->
79
+ <text class="var-text">
80
+ CSS var — --accent: v-bind(textColor)
42
81
  </text>
82
+
83
+ <view :style="{ display: 'flex', flexDirection: 'row', gap: '8px', marginTop: '8px', flexWrap: 'wrap' }">
84
+ <text
85
+ :style="{
86
+ backgroundColor: '#1565c0',
87
+ color: '#fff',
88
+ padding: '6px 12px',
89
+ borderRadius: '4px',
90
+ fontSize: '12px',
91
+ }"
92
+ :bindtap="cycleColor"
93
+ >
94
+ Cycle Color
95
+ </text>
96
+ <text
97
+ :style="{
98
+ backgroundColor: '#2e7d32',
99
+ color: '#fff',
100
+ padding: '6px 12px',
101
+ borderRadius: '4px',
102
+ fontSize: '12px',
103
+ }"
104
+ :bindtap="cycleFontSize"
105
+ >
106
+ Cycle Size
107
+ </text>
108
+ <text
109
+ :style="{
110
+ backgroundColor: '#6a1b9a',
111
+ color: '#fff',
112
+ padding: '6px 12px',
113
+ borderRadius: '4px',
114
+ fontSize: '12px',
115
+ }"
116
+ :bindtap="cycleOpacity"
117
+ >
118
+ Cycle Opacity
119
+ </text>
120
+ </view>
43
121
  </view>
44
122
  </template>
123
+
124
+ <style>
125
+ .title {
126
+ color: v-bind(textColor);
127
+ }
128
+
129
+ .description {
130
+ font-size: 11px;
131
+ color: #555;
132
+ margin-bottom: 8px;
133
+ }
134
+
135
+ .sample-text {
136
+ color: v-bind(textColor);
137
+ font-weight: bold;
138
+ margin-bottom: 4px;
139
+ }
140
+
141
+ .computed-text {
142
+ color: v-bind(invertedColor);
143
+ font-weight: bold;
144
+ margin-bottom: 4px;
145
+ }
146
+
147
+ .border-text {
148
+ color: v-bind('borderStyle.color');
149
+ font-weight: bold;
150
+ margin-bottom: 4px;
151
+ }
152
+
153
+ .opacity-text {
154
+ color: v-bind(textColor);
155
+ opacity: v-bind(opacity);
156
+ font-weight: bold;
157
+ margin-bottom: 4px;
158
+ }
159
+
160
+ .var-text {
161
+ --accent: v-bind(textColor);
162
+ color: var(--accent);
163
+ font-weight: bold;
164
+ margin-bottom: 8px;
165
+ }
166
+ </style>
@@ -0,0 +1,129 @@
1
+ <script setup lang="ts">
2
+ // VBindThreads — audits both style-update paths:
3
+ //
4
+ // LEFT (Background Thread)
5
+ // tap → BG JS handler → reactive ref → useCssVars → SET_STYLE op → MT applies CSS var
6
+ //
7
+ // RIGHT (Main Thread)
8
+ // tap → MT worklet → setStyleProperty() directly (no ops round-trip)
9
+ // + runOnBackground(incrementMtCount) to sync tap count for display
10
+
11
+ import { ref, watch } from 'vue'
12
+ import { useMainThreadRef, runOnBackground, runOnMainThread } from 'vue-lynx'
13
+
14
+ const COLORS = ['#1565c0', '#c62828', '#2e7d32', '#f57f17', '#6a1b9a']
15
+
16
+ // --- Background thread ---
17
+ const bgColorIdx = ref(0)
18
+ const bgColor = ref(COLORS[0]!)
19
+ const bgTapCount = ref(0)
20
+
21
+ function onBgTap() {
22
+ bgTapCount.value++
23
+ bgColorIdx.value = (bgColorIdx.value + 1) % COLORS.length
24
+ bgColor.value = COLORS[bgColorIdx.value]!
25
+ }
26
+
27
+ // --- Main thread ---
28
+ const mtBoxRef = useMainThreadRef(null)
29
+ const mtTapCount = ref(0)
30
+
31
+ // Incremented on BG by runOnBackground() from the MT tap handler
32
+ function incrementMtCount() {
33
+ mtTapCount.value++
34
+ }
35
+
36
+ // MT-local index — lives in MT JS context, not shared with BG reactive state.
37
+ // Captured by the SWC worklet transform into _c.
38
+ let mtColorIdx = 0
39
+
40
+ const onMtTap = () => {
41
+ 'main thread'
42
+ // Cycle color directly on MT — no round-trip through BG
43
+ mtColorIdx = (mtColorIdx + 1) % COLORS.length
44
+ const el = (mtBoxRef as unknown as {
45
+ current?: { setStyleProperty?(k: string, v: string): void }
46
+ }).current
47
+ el?.setStyleProperty?.('background-color', COLORS[mtColorIdx]!)
48
+
49
+ // Sync tap count back to BG for display only
50
+ runOnBackground(incrementMtCount)()
51
+ }
52
+ </script>
53
+
54
+ <template>
55
+ <view :style="{
56
+ display: 'flex',
57
+ flexDirection: 'column',
58
+ backgroundColor: '#f3e5f5',
59
+ padding: '12px',
60
+ borderRadius: '8px',
61
+ marginBottom: '12px',
62
+ }">
63
+ <text :style="{ fontSize: '15px', fontWeight: 'bold', marginBottom: '4px', color: '#4a148c' }">
64
+ Thread comparison — style updates
65
+ </text>
66
+ <text :style="{ fontSize: '11px', color: '#555', marginBottom: '10px' }">
67
+ Both boxes cycle colors on tap. BG path uses v-bind() in CSS; MT path calls setStyleProperty() directly.
68
+ </text>
69
+
70
+ <view :style="{ display: 'flex', flexDirection: 'row', gap: '12px' }">
71
+ <!-- Background thread box -->
72
+ <view :style="{ flex: 1 }">
73
+ <text :style="{ fontSize: '11px', color: '#555', marginBottom: '4px', textAlign: 'center' }">
74
+ Background thread
75
+ </text>
76
+ <view
77
+ class="bg-box"
78
+ :bindtap="onBgTap"
79
+ :style="{
80
+ display: 'flex',
81
+ alignItems: 'center',
82
+ justifyContent: 'center',
83
+ height: '80px',
84
+ borderRadius: '8px',
85
+ }"
86
+ >
87
+ <text :style="{ fontSize: '12px', color: '#fff', fontWeight: 'bold' }">
88
+ Taps: {{ bgTapCount }}
89
+ </text>
90
+ </view>
91
+ <text :style="{ fontSize: '10px', color: '#888', marginTop: '4px', textAlign: 'center' }">
92
+ v-bind(bgColor) in CSS
93
+ </text>
94
+ </view>
95
+
96
+ <!-- Main thread box -->
97
+ <view :style="{ flex: 1 }">
98
+ <text :style="{ fontSize: '11px', color: '#555', marginBottom: '4px', textAlign: 'center' }">
99
+ Main thread
100
+ </text>
101
+ <view
102
+ :main-thread-ref="mtBoxRef"
103
+ :main-thread-bindtap="onMtTap"
104
+ :style="{
105
+ display: 'flex',
106
+ alignItems: 'center',
107
+ justifyContent: 'center',
108
+ height: '80px',
109
+ borderRadius: '8px',
110
+ backgroundColor: '#1565c0',
111
+ }"
112
+ >
113
+ <text :style="{ fontSize: '12px', color: '#fff', fontWeight: 'bold' }">
114
+ Taps: {{ mtTapCount }}
115
+ </text>
116
+ </view>
117
+ <text :style="{ fontSize: '10px', color: '#888', marginTop: '4px', textAlign: 'center' }">
118
+ setStyleProperty() on MT
119
+ </text>
120
+ </view>
121
+ </view>
122
+ </view>
123
+ </template>
124
+
125
+ <style>
126
+ .bg-box {
127
+ background-color: v-bind(bgColor);
128
+ }
129
+ </style>