@situaction/traquiste-mobile 1.0.0-next.2 → 1.0.0-next.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.
Files changed (99) hide show
  1. package/package.json +4 -1
  2. package/.eslintrc.js +0 -5
  3. package/.releaserc +0 -12
  4. package/CLAUDE.md +0 -25
  5. package/app.json +0 -5
  6. package/bitbucket-pipelines.yml +0 -81
  7. package/build/components/Button/Button.stories.d.ts +0 -19
  8. package/build/components/Button/Button.stories.d.ts.map +0 -1
  9. package/build/components/Button/Button.stories.js +0 -95
  10. package/build/components/Button/Button.stories.js.map +0 -1
  11. package/build/components/ButtonAction/ButtonAction.stories.d.ts +0 -13
  12. package/build/components/ButtonAction/ButtonAction.stories.d.ts.map +0 -1
  13. package/build/components/ButtonAction/ButtonAction.stories.js +0 -51
  14. package/build/components/ButtonAction/ButtonAction.stories.js.map +0 -1
  15. package/build/components/ButtonMap/ButtonMap.stories.d.ts +0 -12
  16. package/build/components/ButtonMap/ButtonMap.stories.d.ts.map +0 -1
  17. package/build/components/ButtonMap/ButtonMap.stories.js +0 -36
  18. package/build/components/ButtonMap/ButtonMap.stories.js.map +0 -1
  19. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts +0 -15
  20. package/build/components/ButtonMenu/ButtonMenu.stories.d.ts.map +0 -1
  21. package/build/components/ButtonMenu/ButtonMenu.stories.js +0 -52
  22. package/build/components/ButtonMenu/ButtonMenu.stories.js.map +0 -1
  23. package/build/components/FilterChip/FilterChip.stories.d.ts +0 -15
  24. package/build/components/FilterChip/FilterChip.stories.d.ts.map +0 -1
  25. package/build/components/FilterChip/FilterChip.stories.js +0 -55
  26. package/build/components/FilterChip/FilterChip.stories.js.map +0 -1
  27. package/docs/README.md +0 -73
  28. package/docs/eslint.config.js +0 -22
  29. package/docs/index.html +0 -16
  30. package/docs/package-lock.json +0 -5578
  31. package/docs/package.json +0 -37
  32. package/docs/public/favicon.svg +0 -1
  33. package/docs/public/icons.svg +0 -24
  34. package/docs/src/App.css +0 -184
  35. package/docs/src/App.tsx +0 -38
  36. package/docs/src/assets/hero.png +0 -0
  37. package/docs/src/assets/react.svg +0 -1
  38. package/docs/src/assets/vite.svg +0 -1
  39. package/docs/src/components/Layout.tsx +0 -108
  40. package/docs/src/components/LiveEditor.tsx +0 -294
  41. package/docs/src/components/PropsTable.tsx +0 -101
  42. package/docs/src/components/Sidebar.tsx +0 -103
  43. package/docs/src/components/TableOfContents.tsx +0 -75
  44. package/docs/src/context/ColorModeContext.tsx +0 -34
  45. package/docs/src/index.css +0 -76
  46. package/docs/src/lib/createComponentPage.tsx +0 -270
  47. package/docs/src/main.tsx +0 -13
  48. package/docs/src/pages/Examples.tsx +0 -273
  49. package/docs/src/pages/Home.tsx +0 -70
  50. package/docs/src/pages/components/button-action.ts +0 -88
  51. package/docs/src/pages/components/button-map.ts +0 -67
  52. package/docs/src/pages/components/button-menu.ts +0 -90
  53. package/docs/src/pages/components/button.ts +0 -158
  54. package/docs/src/pages/components/filter-chip.ts +0 -109
  55. package/docs/tsconfig.app.json +0 -32
  56. package/docs/tsconfig.json +0 -7
  57. package/docs/tsconfig.node.json +0 -24
  58. package/docs/vite.config.ts +0 -18
  59. package/ios/.xcode.env +0 -11
  60. package/ios/Podfile +0 -63
  61. package/ios/Podfile.properties.json +0 -4
  62. package/ios/situactiontraquistemobile/AppDelegate.swift +0 -69
  63. package/ios/situactiontraquistemobile/Images.xcassets/AppIcon.appiconset/Contents.json +0 -13
  64. package/ios/situactiontraquistemobile/Images.xcassets/Contents.json +0 -6
  65. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +0 -21
  66. package/ios/situactiontraquistemobile/Images.xcassets/SplashScreenLegacy.imageset/SplashScreenLegacy.png +0 -0
  67. package/ios/situactiontraquistemobile/Info.plist +0 -53
  68. package/ios/situactiontraquistemobile/SplashScreen.storyboard +0 -47
  69. package/ios/situactiontraquistemobile/Supporting/Expo.plist +0 -6
  70. package/ios/situactiontraquistemobile/situactiontraquistemobile-Bridging-Header.h +0 -3
  71. package/ios/situactiontraquistemobile.xcodeproj/project.pbxproj +0 -432
  72. package/ios/situactiontraquistemobile.xcodeproj/xcshareddata/xcschemes/situactiontraquistemobile.xcscheme +0 -88
  73. package/jest.config.js +0 -197
  74. package/src/components/.gitkeep +0 -0
  75. package/src/components/Button/Button.stories.tsx +0 -123
  76. package/src/components/Button/Button.tsx +0 -128
  77. package/src/components/Button/index.ts +0 -2
  78. package/src/components/ButtonAction/ButtonAction.stories.tsx +0 -67
  79. package/src/components/ButtonAction/ButtonAction.tsx +0 -67
  80. package/src/components/ButtonAction/index.ts +0 -2
  81. package/src/components/ButtonMap/ButtonMap.stories.tsx +0 -49
  82. package/src/components/ButtonMap/ButtonMap.tsx +0 -40
  83. package/src/components/ButtonMap/index.ts +0 -2
  84. package/src/components/ButtonMenu/ButtonMenu.stories.tsx +0 -68
  85. package/src/components/ButtonMenu/ButtonMenu.tsx +0 -97
  86. package/src/components/ButtonMenu/index.ts +0 -2
  87. package/src/components/FilterChip/FilterChip.stories.tsx +0 -71
  88. package/src/components/FilterChip/FilterChip.tsx +0 -124
  89. package/src/components/FilterChip/index.ts +0 -2
  90. package/src/constants/colors.ts +0 -2
  91. package/src/context/ThemeContext.tsx +0 -84
  92. package/src/index.ts +0 -23
  93. package/src/theme/index.ts +0 -20
  94. package/src/theme/tokens/dark.ts +0 -160
  95. package/src/theme/tokens/light.ts +0 -166
  96. package/src/theme/type.ts +0 -122
  97. package/src/types/.gitkeep +0 -0
  98. package/src/utils/.gitkeep +0 -0
  99. package/tsconfig.json +0 -9
@@ -1,294 +0,0 @@
1
- /** Demo card: live-editable preview powered by @babel/standalone */
2
- import { useState, useEffect, useRef, useCallback } from 'react'
3
- import type { ReactNode } from 'react'
4
- import ReactForScope from 'react'
5
- import Editor from '@monaco-editor/react'
6
- import { ThemeProvider } from '@situaction/traquiste-mobile'
7
- import { useColorMode } from '../context/ColorModeContext'
8
-
9
- type BabelModule = typeof import('@babel/standalone')
10
-
11
- let babelCache: BabelModule | null = null
12
- let babelLoading: Promise<BabelModule> | null = null
13
-
14
- function loadBabel(): Promise<BabelModule> {
15
- if (babelCache) return Promise.resolve(babelCache)
16
- if (!babelLoading) {
17
- babelLoading = import('@babel/standalone').then((m) => {
18
- babelCache = m
19
- return m
20
- })
21
- }
22
- return babelLoading
23
- }
24
-
25
- interface LiveEditorProps {
26
- title: string
27
- initialCode: string
28
- scope: Record<string, unknown>
29
- }
30
-
31
- const S = {
32
- card: {
33
- border: '1px solid var(--docs-border)',
34
- borderRadius: 12,
35
- overflow: 'hidden',
36
- marginBottom: 20,
37
- boxShadow: 'var(--docs-shadow-sm)',
38
- },
39
- header: {
40
- padding: '10px 14px',
41
- borderBottom: '1px solid var(--docs-border)',
42
- backgroundColor: 'var(--docs-surface)',
43
- display: 'flex',
44
- justifyContent: 'space-between' as const,
45
- alignItems: 'center' as const,
46
- gap: 8,
47
- },
48
- title: {
49
- fontSize: 12,
50
- fontWeight: 600,
51
- color: 'var(--docs-text-muted)',
52
- letterSpacing: '0.03em',
53
- textTransform: 'uppercase' as const,
54
- flex: 1,
55
- },
56
- actions: { display: 'flex', gap: 6, alignItems: 'center' as const },
57
- btn: {
58
- fontSize: 12,
59
- fontWeight: 500,
60
- padding: '4px 10px',
61
- border: '1px solid var(--docs-border)',
62
- borderRadius: 6,
63
- cursor: 'pointer',
64
- backgroundColor: 'var(--docs-bg)',
65
- color: 'var(--docs-text-secondary)',
66
- fontFamily: 'inherit',
67
- whiteSpace: 'nowrap' as const,
68
- },
69
- btnCopied: {
70
- color: 'var(--docs-badge-default-color)',
71
- borderColor: 'var(--docs-badge-default-bg)',
72
- backgroundColor: 'var(--docs-badge-default-bg)',
73
- },
74
- loading: { fontSize: 13, color: 'var(--docs-text-disabled)', fontStyle: 'italic' },
75
- error: {
76
- color: 'var(--docs-badge-name-color)',
77
- fontSize: 12,
78
- fontFamily: 'ui-monospace, Consolas, monospace',
79
- whiteSpace: 'pre-wrap' as const,
80
- margin: 0,
81
- maxWidth: '100%',
82
- overflowX: 'auto' as const,
83
- lineHeight: 1.6,
84
- },
85
- }
86
-
87
- /** 6-dot drag indicator (2 cols × 3 rows) */
88
- function DragDots({ active }: { active: boolean }) {
89
- const color = active ? 'var(--docs-accent)' : 'var(--docs-text-muted)'
90
- const dot = { width: 2, height: 2, borderRadius: '50%', backgroundColor: color } as const
91
- return (
92
- <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
93
- {[0, 1, 2].map((i) => (
94
- <div key={i} style={{ display: 'flex', gap: 3 }}>
95
- <div style={dot} /><div style={dot} />
96
- </div>
97
- ))}
98
- </div>
99
- )
100
- }
101
-
102
- export default function LiveEditor({ title, initialCode, scope }: LiveEditorProps) {
103
- const [code, setCode] = useState(initialCode)
104
- const [showCode, setShowCode] = useState(false)
105
- const [preview, setPreview] = useState<ReactNode>(null)
106
- const [error, setError] = useState<string | null>(null)
107
- const [copied, setCopied] = useState(false)
108
- const [previewWidth, setPreviewWidth] = useState<number | null>(null)
109
- const [isDragging, setIsDragging] = useState(false)
110
- const { mode } = useColorMode()
111
-
112
- const wrapperRef = useRef<HTMLDivElement>(null)
113
- const scopeRef = useRef(scope)
114
- scopeRef.current = scope
115
- const debounceRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
116
-
117
- function handleMouseDown(e: React.MouseEvent) {
118
- e.preventDefault()
119
- const startX = e.clientX
120
- const startWidth = wrapperRef.current?.offsetWidth ?? 600
121
- setIsDragging(true)
122
-
123
- function onMouseMove(ev: MouseEvent) {
124
- const next = Math.max(280, Math.min(1000, startWidth + (ev.clientX - startX)))
125
- setPreviewWidth(next)
126
- }
127
- function onMouseUp() {
128
- setIsDragging(false)
129
- window.removeEventListener('mousemove', onMouseMove)
130
- window.removeEventListener('mouseup', onMouseUp)
131
- }
132
- window.addEventListener('mousemove', onMouseMove)
133
- window.addEventListener('mouseup', onMouseUp)
134
- }
135
-
136
- const evalCode = useCallback((src: string) => {
137
- loadBabel()
138
- .then((Babel) => {
139
- const fullScope = { React: ReactForScope, ...scopeRef.current }
140
- const keys = Object.keys(fullScope)
141
- const wrapped = `const { ${keys.join(', ')} } = __scope__;\nreturn (${src});`
142
- const result = Babel.transform(wrapped, {
143
- presets: ['react'],
144
- filename: 'preview.jsx',
145
- parserOpts: { allowReturnOutsideFunction: true },
146
- })
147
- if (!result.code) throw new Error('Transpilation failed')
148
- // eslint-disable-next-line no-new-func
149
- const fn = new Function('__scope__', result.code)
150
- setPreview(fn(fullScope) as ReactNode)
151
- setError(null)
152
- })
153
- .catch((e: unknown) => {
154
- setError(e instanceof Error ? e.message : String(e))
155
- })
156
- }, [])
157
-
158
- // eslint-disable-next-line react-hooks/exhaustive-deps
159
- useEffect(() => { evalCode(initialCode) }, [])
160
-
161
- function handleChange(value: string | undefined) {
162
- const src = value ?? ''
163
- setCode(src)
164
- clearTimeout(debounceRef.current)
165
- debounceRef.current = setTimeout(() => evalCode(src), 300)
166
- }
167
-
168
- function handleCopy() {
169
- navigator.clipboard.writeText(code).then(() => {
170
- setCopied(true)
171
- setTimeout(() => setCopied(false), 2000)
172
- })
173
- }
174
-
175
- function handleReset() {
176
- setCode(initialCode)
177
- evalCode(initialCode)
178
- }
179
-
180
- const editorHeight = Math.max(80, code.split('\n').length * 19 + 24)
181
-
182
- return (
183
- <div style={{ ...S.card, userSelect: isDragging ? 'none' : undefined }}>
184
- <div style={S.header}>
185
- <span style={S.title}>{title}</span>
186
- <div style={S.actions}>
187
- {code !== initialCode && (
188
- <button style={S.btn} onClick={handleReset}>↺ Reset</button>
189
- )}
190
- <button style={{ ...S.btn, ...(copied ? S.btnCopied : {}) }} onClick={handleCopy}>
191
- {copied ? '✓ Copié' : 'Copier'}
192
- </button>
193
- <button style={S.btn} onClick={() => setShowCode((v) => !v)}>
194
- {showCode ? 'Masquer' : '<> Code'}
195
- </button>
196
- </div>
197
- </div>
198
-
199
- {/* Preview zone */}
200
- <div style={{
201
- backgroundColor: 'var(--docs-bg-subtle)',
202
- display: 'flex',
203
- justifyContent: 'center',
204
- minHeight: 140,
205
- position: 'relative',
206
- transition: 'background 0.2s',
207
- }}>
208
- {/* Resizable wrapper: content + handle side by side */}
209
- <div
210
- ref={wrapperRef}
211
- style={{
212
- display: 'flex',
213
- alignItems: 'stretch',
214
- width: previewWidth ? `${previewWidth}px` : '100%',
215
- maxWidth: '100%',
216
- }}
217
- >
218
- {/* Content */}
219
- <div style={{
220
- flex: 1,
221
- padding: '48px 32px',
222
- display: 'flex',
223
- alignItems: 'center',
224
- justifyContent: 'center',
225
- }}>
226
- <ThemeProvider colorScheme={mode}>
227
- {error
228
- ? <pre style={S.error}>{error}</pre>
229
- : preview ?? <span style={S.loading}>Chargement…</span>}
230
- </ThemeProvider>
231
- </div>
232
-
233
- {/* Drag handle */}
234
- <div
235
- onMouseDown={handleMouseDown}
236
- onDoubleClick={() => setPreviewWidth(null)}
237
- title="Glisser pour redimensionner · Double-clic pour réinitialiser"
238
- style={{
239
- width: 20,
240
- flexShrink: 0,
241
- cursor: 'ew-resize',
242
- display: 'flex',
243
- alignItems: 'center',
244
- justifyContent: 'center',
245
- borderLeft: '1px solid var(--docs-border)',
246
- backgroundColor: isDragging ? 'var(--docs-accent-subtle)' : 'transparent',
247
- transition: 'background 0.15s',
248
- }}
249
- >
250
- <DragDots active={isDragging} />
251
- </div>
252
- </div>
253
-
254
- {/* Width badge */}
255
- {previewWidth && (
256
- <span style={{
257
- position: 'absolute',
258
- bottom: 6,
259
- left: '50%',
260
- transform: 'translateX(-50%)',
261
- fontSize: 11,
262
- fontFamily: 'ui-monospace, Consolas, monospace',
263
- color: 'var(--docs-text-muted)',
264
- backgroundColor: 'var(--docs-surface)',
265
- border: '1px solid var(--docs-border)',
266
- borderRadius: 4,
267
- padding: '2px 6px',
268
- pointerEvents: 'none' as const,
269
- }}>
270
- {previewWidth}px
271
- </span>
272
- )}
273
- </div>
274
-
275
- {showCode && (
276
- <Editor
277
- height={editorHeight}
278
- language="jsx"
279
- theme="vs-dark"
280
- value={code}
281
- onChange={handleChange}
282
- options={{
283
- minimap: { enabled: false },
284
- scrollBeyondLastLine: false,
285
- fontSize: 13,
286
- lineNumbers: 'off',
287
- padding: { top: 14, bottom: 14 },
288
- fontFamily: 'ui-monospace, Consolas, monospace',
289
- }}
290
- />
291
- )}
292
- </div>
293
- )
294
- }
@@ -1,101 +0,0 @@
1
- /** Typed props API table — one row per prop */
2
- export interface PropDef {
3
- name: string
4
- type: string
5
- required: boolean
6
- default?: string
7
- description: string
8
- }
9
-
10
- interface PropsTableProps {
11
- props: PropDef[]
12
- }
13
-
14
- const S = {
15
- table: {
16
- width: '100%',
17
- borderCollapse: 'collapse' as const,
18
- fontSize: 14,
19
- marginTop: 16,
20
- },
21
- th: {
22
- textAlign: 'left' as const,
23
- padding: '10px 12px',
24
- backgroundColor: 'var(--docs-surface)',
25
- borderBottom: '2px solid var(--docs-border)',
26
- fontWeight: 600,
27
- color: 'var(--docs-text-primary)',
28
- fontSize: 13,
29
- },
30
- td: {
31
- padding: '10px 12px',
32
- borderBottom: '1px solid var(--docs-border)',
33
- verticalAlign: 'top' as const,
34
- color: 'var(--docs-text-secondary)',
35
- lineHeight: 1.5,
36
- },
37
- nameMono: {
38
- fontFamily: 'ui-monospace, Consolas, monospace',
39
- fontSize: 13,
40
- color: 'var(--docs-badge-name-color)',
41
- backgroundColor: 'var(--docs-badge-name-bg)',
42
- padding: '2px 5px',
43
- borderRadius: 3,
44
- },
45
- typeMono: {
46
- fontFamily: 'ui-monospace, Consolas, monospace',
47
- fontSize: 13,
48
- color: 'var(--docs-badge-type-color)',
49
- backgroundColor: 'var(--docs-badge-type-bg)',
50
- padding: '2px 5px',
51
- borderRadius: 3,
52
- },
53
- defaultMono: {
54
- fontFamily: 'ui-monospace, Consolas, monospace',
55
- fontSize: 13,
56
- color: 'var(--docs-badge-default-color)',
57
- backgroundColor: 'var(--docs-badge-default-bg)',
58
- padding: '2px 5px',
59
- borderRadius: 3,
60
- },
61
- required: { color: 'var(--docs-badge-name-color)', fontSize: 12, marginLeft: 4 },
62
- empty: { color: 'var(--docs-text-disabled)' },
63
- }
64
-
65
- const HEADERS = ['Nom', 'Type', 'Défaut', 'Description']
66
-
67
- export default function PropsTable({ props }: PropsTableProps) {
68
- return (
69
- <table style={S.table}>
70
- <thead>
71
- <tr>
72
- {HEADERS.map((h) => (
73
- <th key={h} style={S.th}>{h}</th>
74
- ))}
75
- </tr>
76
- </thead>
77
- <tbody>
78
- {props.map((prop, i) => (
79
- <tr
80
- key={prop.name}
81
- style={{ backgroundColor: i % 2 === 0 ? 'var(--docs-bg)' : 'var(--docs-bg-subtle)' }}
82
- >
83
- <td style={S.td}>
84
- <code style={S.nameMono}>{prop.name}</code>
85
- {prop.required && <span style={S.required}>*</span>}
86
- </td>
87
- <td style={S.td}>
88
- <code style={S.typeMono}>{prop.type}</code>
89
- </td>
90
- <td style={S.td}>
91
- {prop.default
92
- ? <code style={S.defaultMono}>{prop.default}</code>
93
- : <span style={S.empty}>—</span>}
94
- </td>
95
- <td style={S.td}>{prop.description}</td>
96
- </tr>
97
- ))}
98
- </tbody>
99
- </table>
100
- )
101
- }
@@ -1,103 +0,0 @@
1
- /** Navigation sidebar — always dark, pill-style active states */
2
- import { useState } from 'react'
3
- import { NavLink } from 'react-router-dom'
4
-
5
- const NAV = [
6
- {
7
- group: 'Général',
8
- items: [{ label: 'Exemples', path: '/examples' }],
9
- },
10
- {
11
- group: 'Composants',
12
- items: [
13
- { label: 'Button', path: '/components/button' },
14
- { label: 'ButtonMenu', path: '/components/button-menu' },
15
- { label: 'ButtonAction', path: '/components/button-action' },
16
- { label: 'ButtonMap', path: '/components/button-map' },
17
- { label: 'FilterChip', path: '/components/filter-chip' },
18
- ],
19
- },
20
- ]
21
-
22
- const S = {
23
- container: {
24
- padding: '20px 0 24px',
25
- height: '100%',
26
- display: 'flex',
27
- flexDirection: 'column' as const,
28
- },
29
- brand: {
30
- display: 'block',
31
- color: '#fff',
32
- fontSize: 15,
33
- fontWeight: 700,
34
- padding: '0 16px 16px',
35
- marginBottom: 8,
36
- textDecoration: 'none',
37
- letterSpacing: '-0.01em',
38
- borderBottom: '1px solid rgba(255,255,255,0.08)',
39
- },
40
- brandSub: {
41
- display: 'block',
42
- fontSize: 11,
43
- color: 'rgba(255,255,255,0.4)',
44
- fontWeight: 400,
45
- marginTop: 2,
46
- },
47
- group: { marginTop: 16, paddingBottom: 8 },
48
- groupLabel: {
49
- display: 'block',
50
- color: 'rgba(255,255,255,0.3)',
51
- fontSize: 10,
52
- fontWeight: 600,
53
- letterSpacing: '0.1em',
54
- textTransform: 'uppercase' as const,
55
- padding: '0 16px 6px',
56
- },
57
- link: (active: boolean, hovered: boolean): React.CSSProperties => ({
58
- display: 'block',
59
- padding: '6px 12px',
60
- margin: '1px 8px',
61
- color: active ? '#fff' : hovered ? 'rgba(255,255,255,0.85)' : 'rgba(255,255,255,0.55)',
62
- textDecoration: 'none',
63
- fontSize: 14,
64
- fontWeight: active ? 500 : 400,
65
- borderRadius: 6,
66
- backgroundColor: active
67
- ? 'rgba(255,255,255,0.1)'
68
- : hovered
69
- ? 'rgba(255,255,255,0.05)'
70
- : 'transparent',
71
- transition: 'background 0.15s, color 0.15s',
72
- }),
73
- }
74
-
75
- export default function Sidebar() {
76
- const [hovered, setHovered] = useState<string | null>(null)
77
-
78
- return (
79
- <div style={S.container}>
80
- <NavLink to="/" style={S.brand}>
81
- traquiste-mobile
82
- <span style={S.brandSub}>by Situaction</span>
83
- </NavLink>
84
-
85
- {NAV.map(({ group, items }) => (
86
- <div key={group} style={S.group}>
87
- <span style={S.groupLabel}>{group}</span>
88
- {items.map(({ label, path }) => (
89
- <NavLink
90
- key={path}
91
- to={path}
92
- style={({ isActive }) => S.link(isActive, hovered === path)}
93
- onMouseEnter={() => setHovered(path)}
94
- onMouseLeave={() => setHovered(null)}
95
- >
96
- {label}
97
- </NavLink>
98
- ))}
99
- </div>
100
- ))}
101
- </div>
102
- )
103
- }
@@ -1,75 +0,0 @@
1
- /** Sticky right-side table of contents with active section tracking */
2
- import { useState, useEffect } from 'react'
3
-
4
- export interface TocItem {
5
- id: string
6
- label: string
7
- }
8
-
9
- interface TableOfContentsProps {
10
- items: TocItem[]
11
- }
12
-
13
- const S = {
14
- container: {
15
- width: 200,
16
- flexShrink: 0,
17
- position: 'sticky' as const,
18
- top: 80,
19
- alignSelf: 'flex-start' as const,
20
- },
21
- heading: {
22
- fontSize: 11,
23
- fontWeight: 700,
24
- letterSpacing: '0.08em',
25
- textTransform: 'uppercase' as const,
26
- color: 'var(--docs-text-muted)',
27
- marginBottom: 12,
28
- },
29
- link: (active: boolean): React.CSSProperties => ({
30
- display: 'block',
31
- fontSize: 13,
32
- padding: '4px 0 4px 12px',
33
- color: active ? 'var(--docs-accent)' : 'var(--docs-text-muted)',
34
- textDecoration: 'none',
35
- borderLeft: `2px solid ${active ? 'var(--docs-accent)' : 'var(--docs-border)'}`,
36
- marginBottom: 2,
37
- fontWeight: active ? 600 : 400,
38
- transition: 'color 0.15s, border-color 0.15s',
39
- }),
40
- }
41
-
42
- export default function TableOfContents({ items }: TableOfContentsProps) {
43
- const [activeId, setActiveId] = useState(items[0]?.id ?? '')
44
-
45
- useEffect(() => {
46
- const observer = new IntersectionObserver(
47
- (entries) => {
48
- const visible = entries.filter((e) => e.isIntersecting)
49
- if (visible.length > 0) setActiveId(visible[0].target.id)
50
- },
51
- { rootMargin: '-10% 0% -70% 0%', threshold: 0 },
52
- )
53
- items.forEach(({ id }) => {
54
- const el = document.getElementById(id)
55
- if (el) observer.observe(el)
56
- })
57
- return () => observer.disconnect()
58
- }, [items])
59
-
60
- return (
61
- <nav style={S.container}>
62
- <p style={S.heading}>Sur cette page</p>
63
- {items.map(({ id, label }) => (
64
- <a
65
- key={id}
66
- href={`#${id}`}
67
- style={S.link(activeId === id)}
68
- onClick={() => setActiveId(id)}
69
- >
70
- {label}
71
- </a>
72
- ))}
73
- </nav>
74
- )
75
- }
@@ -1,34 +0,0 @@
1
- /** Docs-level global color mode state — syncs with data-theme on <html> */
2
- import { createContext, useContext, useState, useEffect } from 'react'
3
- import type { ReactNode } from 'react'
4
- import type { ColorMode } from '@situaction/traquiste-mobile'
5
-
6
- interface ColorModeContextValue {
7
- mode: ColorMode
8
- toggle: () => void
9
- }
10
-
11
- const ColorModeContext = createContext<ColorModeContextValue>({
12
- mode: 'light',
13
- toggle: () => {},
14
- })
15
-
16
- export function ColorModeProvider({ children }: { children: ReactNode }) {
17
- const [mode, setMode] = useState<ColorMode>('light')
18
-
19
- useEffect(() => {
20
- document.documentElement.setAttribute('data-theme', mode)
21
- }, [mode])
22
-
23
- const toggle = () => setMode((m) => (m === 'light' ? 'dark' : 'light'))
24
-
25
- return (
26
- <ColorModeContext.Provider value={{ mode, toggle }}>
27
- {children}
28
- </ColorModeContext.Provider>
29
- )
30
- }
31
-
32
- export function useColorMode(): ColorModeContextValue {
33
- return useContext(ColorModeContext)
34
- }
@@ -1,76 +0,0 @@
1
- *, *::before, *::after {
2
- box-sizing: border-box;
3
- margin: 0;
4
- padding: 0;
5
- }
6
-
7
- /* ===== Light theme (default) ===== */
8
- :root {
9
- --docs-bg: #ffffff;
10
- --docs-bg-subtle: #f9fafb;
11
- --docs-surface: #f4f4f5;
12
- --docs-border: #e4e4e7;
13
-
14
- --docs-text-primary: #18181b;
15
- --docs-text-secondary: #52525b;
16
- --docs-text-muted: #a1a1aa;
17
- --docs-text-disabled: #d4d4d8;
18
-
19
- --docs-accent: #0072E5;
20
- --docs-accent-subtle: rgba(0, 114, 229, 0.08);
21
-
22
- --docs-shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
23
- --docs-shadow-md: 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04);
24
-
25
- --docs-badge-name-color: #dc2626;
26
- --docs-badge-name-bg: #fef2f2;
27
- --docs-badge-type-color: #2563eb;
28
- --docs-badge-type-bg: #eff6ff;
29
- --docs-badge-default-color: #16a34a;
30
- --docs-badge-default-bg: #f0fdf4;
31
- }
32
-
33
- /* ===== Dark theme ===== */
34
- [data-theme="dark"] {
35
- --docs-bg: #09090b;
36
- --docs-bg-subtle: #18181b;
37
- --docs-surface: #27272a;
38
- --docs-border: #3f3f46;
39
-
40
- --docs-text-primary: #fafafa;
41
- --docs-text-secondary: #a1a1aa;
42
- --docs-text-muted: #71717a;
43
- --docs-text-disabled: #52525b;
44
-
45
- --docs-accent: #60a5fa;
46
- --docs-accent-subtle: rgba(96, 165, 250, 0.1);
47
-
48
- --docs-shadow-sm: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
49
- --docs-shadow-md: 0 4px 12px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.3);
50
-
51
- --docs-badge-name-color: #fca5a5;
52
- --docs-badge-name-bg: #450a0a;
53
- --docs-badge-type-color: #93c5fd;
54
- --docs-badge-type-bg: #0c1a2e;
55
- --docs-badge-default-color: #86efac;
56
- --docs-badge-default-bg: #052e16;
57
- }
58
-
59
- html {
60
- scroll-behavior: smooth;
61
- }
62
-
63
- body {
64
- font-family: 'Urbanist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
65
- font-size: 15px;
66
- line-height: 1.6;
67
- -webkit-font-smoothing: antialiased;
68
- -moz-osx-font-smoothing: grayscale;
69
- background: var(--docs-bg);
70
- color: var(--docs-text-primary);
71
- transition: background 0.2s, color 0.2s;
72
- }
73
-
74
- #root {
75
- display: contents;
76
- }