@nebularstreams/overlay-sdk 1.0.0

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.
Files changed (133) hide show
  1. package/package.json +44 -0
  2. package/preview/assets/images/favicon.ico +0 -0
  3. package/preview/assets/images/favicon.png +0 -0
  4. package/preview/assets/images/login-right.webp +0 -0
  5. package/preview/assets/images/nebular.color.100h.png +0 -0
  6. package/preview/assets/images/nebular.color.white.100h.png +0 -0
  7. package/preview/assets/images/nebular.medallion.transparent..png +0 -0
  8. package/preview/assets/images/testcard.png +0 -0
  9. package/preview/assets/webfonts/fa-brands-400.woff2 +0 -0
  10. package/preview/assets/webfonts/fa-solid-900.woff2 +0 -0
  11. package/preview/bundle.min.js +6 -0
  12. package/preview/index.css +28 -0
  13. package/preview/index.html +23 -0
  14. package/readme.md +132 -0
  15. package/skill/nebular-overlay/SKILL.md +56 -0
  16. package/skill/nebular-overlay/agents/openai.yaml +4 -0
  17. package/skill/nebular-overlay/references/examples.md +327 -0
  18. package/skill/nebular-overlay/references/manifest.md +153 -0
  19. package/skill/nebular-overlay/references/runtime-and-design.md +88 -0
  20. package/skill/nebular-overlay/scripts/validate-templates.mjs +244 -0
  21. package/templates/all/broadcast/breaking-news/index.html +100 -0
  22. package/templates/all/broadcast/breaking-news/manifest.json +9 -0
  23. package/templates/all/broadcast/empty/index.html +46 -0
  24. package/templates/all/broadcast/empty/manifest.json +7 -0
  25. package/templates/all/broadcast/empty/nebular.medallion.transparent.png +0 -0
  26. package/templates/all/broadcast/event-countdown/index.html +160 -0
  27. package/templates/all/broadcast/event-countdown/logo.png +0 -0
  28. package/templates/all/broadcast/event-countdown/manifest.json +33 -0
  29. package/templates/all/broadcast/lower-third/index.html +77 -0
  30. package/templates/all/broadcast/lower-third/manifest.json +8 -0
  31. package/templates/all/broadcast/newsticker/index.html +153 -0
  32. package/templates/all/broadcast/newsticker/manifest.json +21 -0
  33. package/templates/all/broadcast/newsticker-frames/background-label-green.png +0 -0
  34. package/templates/all/broadcast/newsticker-frames/background-label-orange.png +0 -0
  35. package/templates/all/broadcast/newsticker-frames/banner.png +0 -0
  36. package/templates/all/broadcast/newsticker-frames/index.html +229 -0
  37. package/templates/all/broadcast/newsticker-frames/manifest.json +20 -0
  38. package/templates/all/broadcast/weather/index.html +382 -0
  39. package/templates/all/broadcast/weather/manifest.json +104 -0
  40. package/templates/all/engagement/call-to-action/index.html +116 -0
  41. package/templates/all/engagement/call-to-action/manifest.json +12 -0
  42. package/templates/all/engagement/chat/index.html +121 -0
  43. package/templates/all/engagement/chat/manifest.json +32 -0
  44. package/templates/all/engagement/post/index.html +132 -0
  45. package/templates/all/engagement/post/manifest.json +31 -0
  46. package/templates/all/gambling/bingo/index.html +227 -0
  47. package/templates/all/gambling/bingo/manifest.json +144 -0
  48. package/templates/all/gambling/keno/index.html +202 -0
  49. package/templates/all/gambling/keno/manifest.json +129 -0
  50. package/templates/all/gambling/lottery/index.html +159 -0
  51. package/templates/all/gambling/lottery/manifest.json +95 -0
  52. package/templates/all/gambling/prize-wall/index.html +256 -0
  53. package/templates/all/gambling/prize-wall/manifest.json +108 -0
  54. package/templates/all/gambling/roulette/index.html +200 -0
  55. package/templates/all/gambling/roulette/manifest.json +78 -0
  56. package/templates/all/gaming/battleship/index.html +578 -0
  57. package/templates/all/gaming/battleship/manifest.json +279 -0
  58. package/templates/all/gaming/gta/mission/index.html +121 -0
  59. package/templates/all/gaming/gta/mission/manifest.json +38 -0
  60. package/templates/all/sports/football/scoreboard/index.html +115 -0
  61. package/templates/all/sports/football/scoreboard/manifest.json +54 -0
  62. package/templates/all/sports/tennis/scoreboard/index.html +120 -0
  63. package/templates/all/sports/tennis/scoreboard/manifest.json +92 -0
  64. package/templates/all/trivia/audience-poll/index.html +60 -0
  65. package/templates/all/trivia/audience-poll/manifest.json +26 -0
  66. package/templates/all/trivia/classic-quiz/index.html +49 -0
  67. package/templates/all/trivia/classic-quiz/manifest.json +15 -0
  68. package/templates/all/trivia/lightning-round/index.html +126 -0
  69. package/templates/all/trivia/lightning-round/manifest.json +27 -0
  70. package/templates/all/trivia/pasapalabra/index.html +249 -0
  71. package/templates/all/trivia/pasapalabra/manifest.json +68 -0
  72. package/templates/all/trivia/quiz-deck/index.html +58 -0
  73. package/templates/all/trivia/quiz-deck/manifest.json +25 -0
  74. package/templates/all/trivia/true-or-false/index.html +81 -0
  75. package/templates/all/trivia/true-or-false/manifest.json +27 -0
  76. package/templates/basic/broadcast/empty/index.html +46 -0
  77. package/templates/basic/broadcast/empty/manifest.json +7 -0
  78. package/templates/basic/broadcast/empty/nebular.medallion.transparent.png +0 -0
  79. package/templates/basic/broadcast/event-countdown/index.html +160 -0
  80. package/templates/basic/broadcast/event-countdown/logo.png +0 -0
  81. package/templates/basic/broadcast/event-countdown/manifest.json +33 -0
  82. package/templates/basic/broadcast/lower-third/index.html +77 -0
  83. package/templates/basic/broadcast/lower-third/manifest.json +8 -0
  84. package/templates/basic/broadcast/newsticker/index.html +153 -0
  85. package/templates/basic/broadcast/newsticker/manifest.json +21 -0
  86. package/templates/basic/broadcast/weather/index.html +382 -0
  87. package/templates/basic/broadcast/weather/manifest.json +104 -0
  88. package/templates/basic/engagement/call-to-action/index.html +116 -0
  89. package/templates/basic/engagement/call-to-action/manifest.json +12 -0
  90. package/templates/basic/engagement/chat/index.html +121 -0
  91. package/templates/basic/engagement/chat/manifest.json +32 -0
  92. package/templates/basic/engagement/post/index.html +132 -0
  93. package/templates/basic/engagement/post/manifest.json +31 -0
  94. package/templates/basic/sports/football/scoreboard/index.html +115 -0
  95. package/templates/basic/sports/football/scoreboard/manifest.json +54 -0
  96. package/templates/basic/sports/tennis/scoreboard/index.html +120 -0
  97. package/templates/basic/sports/tennis/scoreboard/manifest.json +92 -0
  98. package/templates/debug/testing/security-probe/forbidden.js +1 -0
  99. package/templates/debug/testing/security-probe/forbidden.json +1 -0
  100. package/templates/debug/testing/security-probe/forbidden.mp4 +1 -0
  101. package/templates/debug/testing/security-probe/forbidden.svg +1 -0
  102. package/templates/debug/testing/security-probe/index.html +367 -0
  103. package/templates/debug/testing/security-probe/manifest.json +13 -0
  104. package/templates/empty/broadcast/empty/index.html +46 -0
  105. package/templates/empty/broadcast/empty/manifest.json +7 -0
  106. package/templates/empty/broadcast/empty/nebular.medallion.transparent.png +0 -0
  107. package/templates/games/gambling/bingo/index.html +227 -0
  108. package/templates/games/gambling/bingo/manifest.json +56 -0
  109. package/templates/games/gambling/keno/index.html +202 -0
  110. package/templates/games/gambling/keno/manifest.json +129 -0
  111. package/templates/games/gambling/lottery/index.html +159 -0
  112. package/templates/games/gambling/lottery/manifest.json +95 -0
  113. package/templates/games/gambling/prize-wall/index.html +256 -0
  114. package/templates/games/gambling/prize-wall/manifest.json +108 -0
  115. package/templates/games/gambling/roulette/index.html +200 -0
  116. package/templates/games/gambling/roulette/manifest.json +78 -0
  117. package/templates/games/gaming/battleship/index.html +578 -0
  118. package/templates/games/gaming/battleship/manifest.json +279 -0
  119. package/templates/games/gaming/gta/mission/index.html +121 -0
  120. package/templates/games/gaming/gta/mission/manifest.json +38 -0
  121. package/templates/games/trivia/audience-poll/index.html +60 -0
  122. package/templates/games/trivia/audience-poll/manifest.json +26 -0
  123. package/templates/games/trivia/classic-quiz/index.html +49 -0
  124. package/templates/games/trivia/classic-quiz/manifest.json +15 -0
  125. package/templates/games/trivia/lightning-round/index.html +126 -0
  126. package/templates/games/trivia/lightning-round/manifest.json +27 -0
  127. package/templates/games/trivia/pasapalabra/index.html +249 -0
  128. package/templates/games/trivia/pasapalabra/manifest.json +68 -0
  129. package/templates/games/trivia/quiz-deck/index.html +58 -0
  130. package/templates/games/trivia/quiz-deck/manifest.json +25 -0
  131. package/templates/games/trivia/true-or-false/index.html +81 -0
  132. package/templates/games/trivia/true-or-false/manifest.json +27 -0
  133. package/tool/cli.cjs +7 -0
@@ -0,0 +1,202 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Keno Live Board</title>
6
+ <style>
7
+ * {
8
+ box-sizing: border-box
9
+ }
10
+
11
+ html, body {
12
+ width: 100%;
13
+ height: 100%;
14
+ margin: 0;
15
+ overflow: hidden;
16
+ background: transparent
17
+ }
18
+
19
+ body {
20
+ font-family: Inter, system-ui, sans-serif;
21
+ color: #fff
22
+ }
23
+
24
+ .keno {
25
+ position: absolute;
26
+ inset: auto 5% 9% 5%;
27
+ display: grid;
28
+ grid-template-columns: 19rem 1fr;
29
+ gap: .9rem;
30
+ }
31
+
32
+ .side, .board {
33
+ background: #081b2df2;
34
+ border: 1px solid #ffffff29;
35
+ border-radius: 1rem;
36
+ box-shadow: 0 1.3rem 3.5rem #0006
37
+ }
38
+
39
+ .side {
40
+ display: flex;
41
+ flex-direction: column;
42
+ align-items: center;
43
+ justify-content: center;
44
+ padding: 1.3rem;
45
+ background: radial-gradient(circle at 50% 30%, #174a67, #071725 70%);
46
+ text-align: center
47
+ }
48
+
49
+ .logo {
50
+ color: #61ddff;
51
+ font-size: 1.15rem;
52
+ font-weight: 900;
53
+ letter-spacing: .2em
54
+ }
55
+
56
+ .latest {
57
+ width: 10.5rem;
58
+ height: 10.5rem;
59
+ margin: 1.2rem;
60
+ display: grid;
61
+ place-items: center;
62
+ border-radius: 50%;
63
+ background: radial-gradient(circle at 32% 25%, #fff 0 6%, #73f2ff 28%, #1689c5 72%);
64
+ border: .5rem solid #d8faff;
65
+ color: #062239;
66
+ font-size: 4.5rem;
67
+ font-weight: 950;
68
+ animation: pop .4s ease
69
+ }
70
+
71
+ .title {
72
+ font-size: 1.9rem;
73
+ font-weight: 900
74
+ }
75
+
76
+ .subtitle {
77
+ margin-top: .4rem;
78
+ color: #9eb9c9;
79
+ font-size: 1.25rem;
80
+ line-height: 1.3
81
+ }
82
+
83
+ .count {
84
+ margin-top: 1.2rem;
85
+ color: #61ddff;
86
+ font-size: 1.15rem;
87
+ font-weight: 850
88
+ }
89
+
90
+ .board {
91
+ padding: 1rem
92
+ }
93
+
94
+ .header {
95
+ display: flex;
96
+ justify-content: space-between;
97
+ margin-bottom: .75rem
98
+ }
99
+
100
+ .header strong {
101
+ font-size: 1.3rem;
102
+ letter-spacing: .1em
103
+ }
104
+
105
+ .header span {
106
+ color: #91aebf;
107
+ font-size: 1rem;
108
+ font-weight: 750
109
+ }
110
+
111
+ .numbers {
112
+ display: grid;
113
+ grid-template-columns:repeat(10, minmax(0, 1fr));
114
+ gap: .36rem
115
+ }
116
+
117
+ .number {
118
+ height: 3.6rem;
119
+ display: grid;
120
+ place-items: center;
121
+ border-radius: .45rem;
122
+ background: #ffffff0a;
123
+ border: 1px solid #ffffff14;
124
+ color: #ffffff54;
125
+ font-size: 1.2rem;
126
+ font-weight: 800
127
+ }
128
+
129
+ .number.hit {
130
+ background: #eefcff;
131
+ color: #08233a;
132
+ border-color: #fff
133
+ }
134
+
135
+ .number.latest {
136
+ width: auto;
137
+ height: 3.6rem;
138
+ margin: 0;
139
+ border: .15rem solid #bbf7ff;
140
+ background: #25c5ee;
141
+ color: #062239;
142
+ font-size: 1.35rem;
143
+ transform: scale(1.12);
144
+ box-shadow: 0 .6rem 1.3rem #0008;
145
+ z-index: 2
146
+ }
147
+
148
+ @keyframes pop {
149
+ from {
150
+ opacity: 0;
151
+ transform: scale(.45) rotate(18deg)
152
+ }
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <main class="keno">
158
+ <aside class="side">
159
+ <div class="logo">KENO LIVE</div>
160
+ <div class="latest" id="latest">63</div>
161
+ <div class="title" id="title">Evening Draw</div>
162
+ <div class="subtitle" id="subtitle">Watch your numbers light up</div>
163
+ <div class="count" id="count">9 numbers drawn</div>
164
+ </aside>
165
+ <section class="board">
166
+ <div class="header"><strong>DRAW BOARD</strong><span>1–80 · LATEST NUMBER IN BLUE</span></div>
167
+ <div class="numbers" id="numbers"></div>
168
+ </section>
169
+ </main>
170
+ <script>
171
+ const
172
+ ALL = Array.from({length: 80}, (_, i) => i + 1);
173
+
174
+ const $ = id => document.getElementById(id), cells = new Map();
175
+
176
+ ALL.forEach(n => {
177
+ const cell = document.createElement("div");
178
+ cell.className = "number";
179
+ cell.textContent = n;
180
+ $("numbers").append(cell);
181
+ cells.set(n, cell)
182
+ });
183
+
184
+ function render(numbers) {
185
+ const values = (Array.isArray(numbers) ? numbers : []).map(Number).filter(n => n >= 1 && n <= 80), hits = new Set(values), latest = values.at(-1);
186
+ cells.forEach((cell, n) => {
187
+ cell.classList.toggle("hit", hits.has(n));
188
+ cell.classList.toggle("latest", n === latest)
189
+ });
190
+ $("latest").textContent = latest ?? "—";
191
+ $("count").textContent = `${hits.size} ${hits.size === 1 ? "number" : "numbers"} drawn`
192
+ }
193
+
194
+ window.addEventListener("nebular-overlay:update", ({detail}) => {
195
+ if (detail.content?.title != null) $("title").textContent = detail.content.title;
196
+ if (detail.content?.subtitle != null) $("subtitle").textContent = detail.content.subtitle;
197
+ if (detail.draw?.numbers != null) render(detail.draw.numbers)
198
+ });
199
+
200
+ </script>
201
+ </body>
202
+ </html>
@@ -0,0 +1,129 @@
1
+ {
2
+ "instructions": "Select all numbers drawn in the current game and edit the draw title or subtitle as needed. Press Update after each draw to refresh the board. Use Reset draw to clear the numbers, then press Update to publish the reset.",
3
+ "meta": {
4
+ "content/title": {
5
+ "type": "string",
6
+ "phase": "edit",
7
+ "label": "Draw title", "hint": "Enter draw title",
8
+ "default": "Evening Draw"
9
+ },
10
+ "content/subtitle": {
11
+ "type": "string",
12
+ "phase": "edit",
13
+ "label": "Subtitle", "hint": "Enter subtitle",
14
+ "default": "Watch your numbers light up"
15
+ },
16
+ "draw/numbers": {
17
+ "type": "multi",
18
+ "phase": "play",
19
+ "container": "big",
20
+ "label": "Drawn numbers", "hint": "Numbers selected in the current draw",
21
+ "choose": [
22
+ 1,
23
+ 2,
24
+ 3,
25
+ 4,
26
+ 5,
27
+ 6,
28
+ 7,
29
+ 8,
30
+ 9,
31
+ 10,
32
+ 11,
33
+ 12,
34
+ 13,
35
+ 14,
36
+ 15,
37
+ 16,
38
+ 17,
39
+ 18,
40
+ 19,
41
+ 20,
42
+ 21,
43
+ 22,
44
+ 23,
45
+ 24,
46
+ 25,
47
+ 26,
48
+ 27,
49
+ 28,
50
+ 29,
51
+ 30,
52
+ 31,
53
+ 32,
54
+ 33,
55
+ 34,
56
+ 35,
57
+ 36,
58
+ 37,
59
+ 38,
60
+ 39,
61
+ 40,
62
+ 41,
63
+ 42,
64
+ 43,
65
+ 44,
66
+ 45,
67
+ 46,
68
+ 47,
69
+ 48,
70
+ 49,
71
+ 50,
72
+ 51,
73
+ 52,
74
+ 53,
75
+ 54,
76
+ 55,
77
+ 56,
78
+ 57,
79
+ 58,
80
+ 59,
81
+ 60,
82
+ 61,
83
+ 62,
84
+ 63,
85
+ 64,
86
+ 65,
87
+ 66,
88
+ 67,
89
+ 68,
90
+ 69,
91
+ 70,
92
+ 71,
93
+ 72,
94
+ 73,
95
+ 74,
96
+ 75,
97
+ 76,
98
+ 77,
99
+ 78,
100
+ 79,
101
+ 80
102
+ ],
103
+ "cols": 10,
104
+ "rows": 8,
105
+ "responsive": true,
106
+ "minCellWidth": "2.54rem",
107
+ "default": [
108
+ 4,
109
+ 11,
110
+ 23,
111
+ 37,
112
+ 44,
113
+ 52,
114
+ 58,
115
+ 71,
116
+ 63
117
+ ]
118
+ },
119
+ "draw/reset": {
120
+ "type": "reset",
121
+ "phase": "play",
122
+ "icon": "undo",
123
+ "text": "Reset draw", "hint": "Clear every number from the current draw",
124
+ "values": {
125
+ "draw/numbers": []
126
+ }
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,159 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Lottery Draw</title>
6
+ <style>
7
+ * {
8
+ box-sizing: border-box
9
+ }
10
+
11
+ html, body {
12
+ width: 100%;
13
+ height: 100%;
14
+ margin: 0;
15
+ overflow: hidden;
16
+ background: transparent
17
+ }
18
+
19
+ body {
20
+ font-family: Inter, system-ui, sans-serif;
21
+ color: #fff
22
+ }
23
+
24
+ .draw {
25
+ position: absolute;
26
+ left: 6%;
27
+ right: 6%;
28
+ bottom: 9%;
29
+ padding: 1.5rem 1.8rem 1.8rem;
30
+ background: linear-gradient(135deg, #281451f2, #0c1838f2);
31
+ border: 1px solid #ffffff38;
32
+ border-radius: 1.4rem;
33
+ box-shadow: 0 1.5rem 4rem #0006
34
+ }
35
+
36
+ .head {
37
+ display: flex;
38
+ justify-content: space-between;
39
+ align-items: end
40
+ }
41
+
42
+ .eyebrow {
43
+ color: #8ce8ff;
44
+ font-size: 1.2rem;
45
+ font-weight: 850;
46
+ letter-spacing: .18em
47
+ }
48
+
49
+ .title {
50
+ margin-top: .25rem;
51
+ font-size: 2.6rem;
52
+ font-weight: 950
53
+ }
54
+
55
+ .status {
56
+ color: #c8c6dd;
57
+ font-size: 1.3rem;
58
+ font-weight: 750
59
+ }
60
+
61
+ .balls {
62
+ display: flex;
63
+ justify-content: center;
64
+ align-items: center;
65
+ gap: 1.1rem;
66
+ min-height: 12rem;
67
+ margin-top: 1.2rem;
68
+ padding: 1.2rem;
69
+ border-radius: 1rem;
70
+ background: #ffffff0c
71
+ }
72
+
73
+ .empty {
74
+ color: #ffffff66;
75
+ font-size: 1.6rem;
76
+ font-weight: 750
77
+ }
78
+
79
+ .ball {
80
+ width: 8rem;
81
+ height: 8rem;
82
+ display: grid;
83
+ place-items: center;
84
+ border-radius: 50%;
85
+ background: radial-gradient(circle at 32% 25%, #fff 0 7%, #70e2ff 29%, #385ddb 72%);
86
+ border: .45rem solid #ffffffc7;
87
+ color: #10173c;
88
+ font-size: 3rem;
89
+ font-weight: 950;
90
+ box-shadow: inset -.7rem -.8rem 1.2rem #14217666, 0 .8rem 1.6rem #0006
91
+ }
92
+
93
+ .ball.latest {
94
+ width: 9.5rem;
95
+ height: 9.5rem;
96
+ background: radial-gradient(circle at 32% 25%, #fff 0 7%, #ffe66d 29%, #ff8d21 72%);
97
+ animation: drop .45s cubic-bezier(.2, .9, .35, 1.25)
98
+ }
99
+
100
+ .order {
101
+ margin-top: .65rem;
102
+ text-align: center;
103
+ color: #aaa9c3;
104
+ font-size: 1.15rem;
105
+ font-weight: 800;
106
+ letter-spacing: .1em
107
+ }
108
+
109
+ @keyframes drop {
110
+ from {
111
+ opacity: 0;
112
+ transform: translateY(-4rem) rotate(-20deg) scale(.6)
113
+ }
114
+ }
115
+ </style>
116
+ </head>
117
+ <body>
118
+ <section class="draw">
119
+ <div class="head">
120
+ <div>
121
+ <div class="eyebrow" id="eyebrow">OFFICIAL DRAW</div>
122
+ <div class="title" id="title">Lucky 49</div>
123
+ </div>
124
+ <div class="status" id="status">6 numbers drawn</div>
125
+ </div>
126
+ <div class="balls" id="balls"></div>
127
+ <div class="order">NUMBERS ARE DISPLAYED IN DRAW ORDER</div>
128
+ </section>
129
+ <script>
130
+ const ALL = Array.from({length: 49}, (_, i) => i + 1);
131
+ const $ = id => document.getElementById(id);
132
+
133
+ function render(numbers) {
134
+ const values = (Array.isArray(numbers) ? numbers : []).map(Number).filter(n => n >= 1 && n <= 49), holder = $("balls");
135
+ holder.replaceChildren();
136
+ if (!values.length) {
137
+ const empty = document.createElement("div");
138
+ empty.className = "empty";
139
+ empty.textContent = "Waiting for the first number…";
140
+ holder.append(empty)
141
+ } else values.forEach((number, index) => {
142
+ const ball = document.createElement("div");
143
+ ball.className = `ball ${index === values.length - 1 ? "latest" : ""}`;
144
+ ball.textContent = number;
145
+ holder.append(ball)
146
+ });
147
+ $("status").textContent = `${values.length} ${values.length === 1 ? "number" : "numbers"} drawn`
148
+ }
149
+
150
+ window.addEventListener("nebular-overlay:update", ({detail}) => {
151
+ if (detail.content?.eyebrow != null) $("eyebrow").textContent = detail.content.eyebrow;
152
+ if (detail.content?.title != null) $("title").textContent = detail.content.title;
153
+ if (detail.draw?.numbers != null) render(detail.draw.numbers)
154
+ });
155
+
156
+
157
+ </script>
158
+ </body>
159
+ </html>
@@ -0,0 +1,95 @@
1
+ {
2
+ "instructions": "Select the official drawn numbers, edit the lottery title and draw label if needed, then press Update to publish the result strip. Use Reset draw to clear the numbers, then press Update to publish the reset.",
3
+ "meta": {
4
+ "content/eyebrow": {
5
+ "type": "string",
6
+ "phase": "edit",
7
+ "label": "Draw label", "hint": "Enter short label",
8
+ "default": "OFFICIAL DRAW"
9
+ },
10
+ "content/title": {
11
+ "type": "string",
12
+ "phase": "edit",
13
+ "label": "Lottery title", "hint": "Enter lottery title",
14
+ "default": "Lucky 49"
15
+ },
16
+ "draw/numbers": {
17
+ "type": "multi",
18
+ "phase": "play",
19
+ "container": "big",
20
+ "label": "Drawn numbers", "hint": "Numbers selected in the current draw",
21
+ "choose": [
22
+ 1,
23
+ 2,
24
+ 3,
25
+ 4,
26
+ 5,
27
+ 6,
28
+ 7,
29
+ 8,
30
+ 9,
31
+ 10,
32
+ 11,
33
+ 12,
34
+ 13,
35
+ 14,
36
+ 15,
37
+ 16,
38
+ 17,
39
+ 18,
40
+ 19,
41
+ 20,
42
+ 21,
43
+ 22,
44
+ 23,
45
+ 24,
46
+ 25,
47
+ 26,
48
+ 27,
49
+ 28,
50
+ 29,
51
+ 30,
52
+ 31,
53
+ 32,
54
+ 33,
55
+ 34,
56
+ 35,
57
+ 36,
58
+ 37,
59
+ 38,
60
+ 39,
61
+ 40,
62
+ 41,
63
+ 42,
64
+ 43,
65
+ 44,
66
+ 45,
67
+ 46,
68
+ 47,
69
+ 48,
70
+ 49
71
+ ],
72
+ "cols": 7,
73
+ "rows": 7,
74
+ "responsive": true,
75
+ "minCellWidth": "2.54rem",
76
+ "default": [
77
+ 7,
78
+ 14,
79
+ 22,
80
+ 31,
81
+ 38,
82
+ 46
83
+ ]
84
+ },
85
+ "draw/reset": {
86
+ "type": "reset",
87
+ "phase": "play",
88
+ "icon": "undo",
89
+ "text": "Reset draw", "hint": "Clear every number from the current draw",
90
+ "values": {
91
+ "draw/numbers": []
92
+ }
93
+ }
94
+ }
95
+ }