reflex-components-code 0.9.0__tar.gz

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.
@@ -0,0 +1,24 @@
1
+ **/.DS_Store
2
+ **/*.pyc
3
+ assets/external/*
4
+ dist/*
5
+ examples/
6
+ .web
7
+ .states
8
+ .idea
9
+ .vscode
10
+ .coverage
11
+ .coverage.*
12
+ .venv
13
+ venv
14
+ requirements.txt
15
+ .pyi_generator_last_run
16
+ .pyi_generator_diff
17
+ reflex.db
18
+ .codspeed
19
+ .env
20
+ .env.*
21
+ node_modules
22
+ package-lock.json
23
+ *.pyi
24
+ .pre-commit-config.yaml
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: reflex-components-code
3
+ Version: 0.9.0
4
+ Summary: Reflex code display components.
5
+ Author-email: Khaleel Al-Adhami <khaleel@reflex.dev>
6
+ Maintainer-email: Khaleel Al-Adhami <khaleel@reflex.dev>
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: reflex-components-core
9
+ Requires-Dist: reflex-components-lucide
10
+ Requires-Dist: reflex-components-radix
11
+ Description-Content-Type: text/markdown
12
+
13
+ # reflex-components-code
14
+
15
+ Reflex code display components.
@@ -0,0 +1,3 @@
1
+ # reflex-components-code
2
+
3
+ Reflex code display components.
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "reflex-components-code"
3
+ dynamic = ["version"]
4
+ description = "Reflex code display components."
5
+ readme = "README.md"
6
+ authors = [{ name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" }]
7
+ maintainers = [{ name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" }]
8
+ requires-python = ">=3.10"
9
+ dependencies = [
10
+ "reflex-components-core",
11
+ "reflex-components-lucide",
12
+ "reflex-components-radix",
13
+ ]
14
+
15
+ [tool.hatch.version]
16
+ source = "uv-dynamic-versioning"
17
+
18
+ [tool.uv-dynamic-versioning]
19
+ pattern-prefix = "reflex-components-code-"
20
+ fallback-version = "0.0.0dev0"
21
+
22
+ [tool.hatch.build]
23
+ targets.sdist.artifacts = ["*.pyi"]
24
+ targets.wheel.artifacts = ["*.pyi"]
25
+
26
+ [tool.hatch.build.hooks.reflex-pyi]
27
+ dependencies = [
28
+ "ruff",
29
+ "reflex-base",
30
+ "reflex-components-core",
31
+ "reflex-components-lucide",
32
+ "reflex-components-radix",
33
+ "reflex-components-sonner",
34
+ ]
35
+
36
+ [build-system]
37
+ requires = ["hatchling", "uv-dynamic-versioning", "hatch-reflex-pyi"]
38
+ build-backend = "hatchling.build"
@@ -0,0 +1 @@
1
+ """Reflex code display components."""
@@ -0,0 +1,524 @@
1
+ """A code component."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ from typing import ClassVar, Literal
7
+
8
+ from reflex_base.components.component import Component, ComponentNamespace, field
9
+ from reflex_base.constants.colors import Color
10
+ from reflex_base.event import set_clipboard
11
+ from reflex_base.style import Style
12
+ from reflex_base.utils import format
13
+ from reflex_base.utils.imports import ImportVar
14
+ from reflex_base.vars.base import LiteralVar, Var, VarData
15
+ from reflex_components_core.core.cond import color_mode_cond
16
+ from reflex_components_core.core.markdown_component_map import MarkdownComponentMap
17
+ from reflex_components_radix.themes.components.button import Button
18
+ from reflex_components_radix.themes.layout.box import Box
19
+
20
+ LiteralCodeLanguage = Literal[
21
+ "abap",
22
+ "abnf",
23
+ "actionscript",
24
+ "ada",
25
+ "agda",
26
+ "al",
27
+ "antlr4",
28
+ "apacheconf",
29
+ "apex",
30
+ "apl",
31
+ "applescript",
32
+ "aql",
33
+ "arduino",
34
+ "arff",
35
+ "asciidoc",
36
+ "asm6502",
37
+ "asmatmel",
38
+ "aspnet",
39
+ "autohotkey",
40
+ "autoit",
41
+ "avisynth",
42
+ "avro-idl",
43
+ "bash",
44
+ "basic",
45
+ "batch",
46
+ "bbcode",
47
+ "bicep",
48
+ "birb",
49
+ "bison",
50
+ "bnf",
51
+ "brainfuck",
52
+ "brightscript",
53
+ "bro",
54
+ "bsl",
55
+ "c",
56
+ "cfscript",
57
+ "chaiscript",
58
+ "cil",
59
+ "clike",
60
+ "clojure",
61
+ "cmake",
62
+ "cobol",
63
+ "coffeescript",
64
+ "concurnas",
65
+ "coq",
66
+ "core",
67
+ "cpp",
68
+ "crystal",
69
+ "csharp",
70
+ "cshtml",
71
+ "csp",
72
+ "css",
73
+ "css-extras",
74
+ "csv",
75
+ "cypher",
76
+ "d",
77
+ "dart",
78
+ "dataweave",
79
+ "dax",
80
+ "dhall",
81
+ "diff",
82
+ "django",
83
+ "dns-zone-file",
84
+ "docker",
85
+ "dot",
86
+ "ebnf",
87
+ "editorconfig",
88
+ "eiffel",
89
+ "ejs",
90
+ "elixir",
91
+ "elm",
92
+ "erb",
93
+ "erlang",
94
+ "etlua",
95
+ "excel-formula",
96
+ "factor",
97
+ "false",
98
+ "firestore-security-rules",
99
+ "flow",
100
+ "fortran",
101
+ "fsharp",
102
+ "ftl",
103
+ "gap",
104
+ "gcode",
105
+ "gdscript",
106
+ "gedcom",
107
+ "gherkin",
108
+ "git",
109
+ "glsl",
110
+ "gml",
111
+ "gn",
112
+ "go",
113
+ "go-module",
114
+ "graphql",
115
+ "groovy",
116
+ "haml",
117
+ "handlebars",
118
+ "haskell",
119
+ "haxe",
120
+ "hcl",
121
+ "hlsl",
122
+ "hoon",
123
+ "hpkp",
124
+ "hsts",
125
+ "http",
126
+ "ichigojam",
127
+ "icon",
128
+ "icu-message-format",
129
+ "idris",
130
+ "iecst",
131
+ "ignore",
132
+ "index",
133
+ "inform7",
134
+ "ini",
135
+ "io",
136
+ "j",
137
+ "java",
138
+ "javadoc",
139
+ "javadoclike",
140
+ "javascript",
141
+ "javastacktrace",
142
+ "jexl",
143
+ "jolie",
144
+ "jq",
145
+ "js-extras",
146
+ "js-templates",
147
+ "jsdoc",
148
+ "json",
149
+ "json5",
150
+ "jsonp",
151
+ "jsstacktrace",
152
+ "jsx",
153
+ "julia",
154
+ "keepalived",
155
+ "keyman",
156
+ "kotlin",
157
+ "kumir",
158
+ "kusto",
159
+ "latex",
160
+ "latte",
161
+ "less",
162
+ "lilypond",
163
+ "liquid",
164
+ "lisp",
165
+ "livescript",
166
+ "llvm",
167
+ "log",
168
+ "lolcode",
169
+ "lua",
170
+ "magma",
171
+ "makefile",
172
+ "markdown",
173
+ "markup",
174
+ "markup-templating",
175
+ "matlab",
176
+ "maxscript",
177
+ "mel",
178
+ "mermaid",
179
+ "mizar",
180
+ "mongodb",
181
+ "monkey",
182
+ "moonscript",
183
+ "n1ql",
184
+ "n4js",
185
+ "nand2tetris-hdl",
186
+ "naniscript",
187
+ "nasm",
188
+ "neon",
189
+ "nevod",
190
+ "nginx",
191
+ "nim",
192
+ "nix",
193
+ "nsis",
194
+ "objectivec",
195
+ "ocaml",
196
+ "opencl",
197
+ "openqasm",
198
+ "oz",
199
+ "parigp",
200
+ "parser",
201
+ "pascal",
202
+ "pascaligo",
203
+ "pcaxis",
204
+ "peoplecode",
205
+ "perl",
206
+ "php",
207
+ "php-extras",
208
+ "phpdoc",
209
+ "plsql",
210
+ "powerquery",
211
+ "powershell",
212
+ "processing",
213
+ "prolog",
214
+ "promql",
215
+ "properties",
216
+ "protobuf",
217
+ "psl",
218
+ "pug",
219
+ "puppet",
220
+ "pure",
221
+ "purebasic",
222
+ "purescript",
223
+ "python",
224
+ "q",
225
+ "qml",
226
+ "qore",
227
+ "qsharp",
228
+ "r",
229
+ "racket",
230
+ "reason",
231
+ "regex",
232
+ "rego",
233
+ "renpy",
234
+ "rest",
235
+ "rip",
236
+ "roboconf",
237
+ "robotframework",
238
+ "ruby",
239
+ "rust",
240
+ "sas",
241
+ "sass",
242
+ "scala",
243
+ "scheme",
244
+ "scss",
245
+ "shell-session",
246
+ "smali",
247
+ "smalltalk",
248
+ "smarty",
249
+ "sml",
250
+ "solidity",
251
+ "solution-file",
252
+ "soy",
253
+ "sparql",
254
+ "splunk-spl",
255
+ "sqf",
256
+ "sql",
257
+ "squirrel",
258
+ "stan",
259
+ "stylus",
260
+ "swift",
261
+ "systemd",
262
+ "t4-cs",
263
+ "t4-templating",
264
+ "t4-vb",
265
+ "tap",
266
+ "tcl",
267
+ "textile",
268
+ "toml",
269
+ "tremor",
270
+ "tsx",
271
+ "tt2",
272
+ "turtle",
273
+ "twig",
274
+ "typescript",
275
+ "typoscript",
276
+ "unrealscript",
277
+ "uorazor",
278
+ "uri",
279
+ "v",
280
+ "vala",
281
+ "vbnet",
282
+ "velocity",
283
+ "verilog",
284
+ "vhdl",
285
+ "vim",
286
+ "visual-basic",
287
+ "warpscript",
288
+ "wasm",
289
+ "web-idl",
290
+ "wiki",
291
+ "wolfram",
292
+ "wren",
293
+ "xeora",
294
+ "xml-doc",
295
+ "xojo",
296
+ "xquery",
297
+ "yaml",
298
+ "yang",
299
+ "zig",
300
+ ]
301
+
302
+
303
+ def construct_theme_var(theme: str) -> Var[Theme]:
304
+ """Construct a theme var.
305
+
306
+ Args:
307
+ theme: The theme to construct.
308
+
309
+ Returns:
310
+ The constructed theme var.
311
+ """
312
+ return Var(
313
+ theme,
314
+ _var_data=VarData(
315
+ imports={
316
+ f"react-syntax-highlighter/dist/esm/styles/prism/{format.to_kebab_case(theme)}": [
317
+ ImportVar(tag=theme, is_default=True, install=False)
318
+ ]
319
+ }
320
+ ),
321
+ )
322
+
323
+
324
+ @dataclasses.dataclass(init=False)
325
+ class Theme:
326
+ """Themes for the CodeBlock component."""
327
+
328
+ a11y_dark: ClassVar[Var[Theme]] = construct_theme_var("a11yDark")
329
+ atom_dark: ClassVar[Var[Theme]] = construct_theme_var("atomDark")
330
+ cb: ClassVar[Var[Theme]] = construct_theme_var("cb")
331
+ coldark_cold: ClassVar[Var[Theme]] = construct_theme_var("coldarkCold")
332
+ coldark_dark: ClassVar[Var[Theme]] = construct_theme_var("coldarkDark")
333
+ coy: ClassVar[Var[Theme]] = construct_theme_var("coy")
334
+ coy_without_shadows: ClassVar[Var[Theme]] = construct_theme_var("coyWithoutShadows")
335
+ darcula: ClassVar[Var[Theme]] = construct_theme_var("darcula")
336
+ dark: ClassVar[Var[Theme]] = construct_theme_var("oneDark")
337
+ dracula: ClassVar[Var[Theme]] = construct_theme_var("dracula")
338
+ duotone_dark: ClassVar[Var[Theme]] = construct_theme_var("duotoneDark")
339
+ duotone_earth: ClassVar[Var[Theme]] = construct_theme_var("duotoneEarth")
340
+ duotone_forest: ClassVar[Var[Theme]] = construct_theme_var("duotoneForest")
341
+ duotone_light: ClassVar[Var[Theme]] = construct_theme_var("duotoneLight")
342
+ duotone_sea: ClassVar[Var[Theme]] = construct_theme_var("duotoneSea")
343
+ duotone_space: ClassVar[Var[Theme]] = construct_theme_var("duotoneSpace")
344
+ funky: ClassVar[Var[Theme]] = construct_theme_var("funky")
345
+ ghcolors: ClassVar[Var[Theme]] = construct_theme_var("ghcolors")
346
+ gruvbox_dark: ClassVar[Var[Theme]] = construct_theme_var("gruvboxDark")
347
+ gruvbox_light: ClassVar[Var[Theme]] = construct_theme_var("gruvboxLight")
348
+ holi_theme: ClassVar[Var[Theme]] = construct_theme_var("holiTheme")
349
+ hopscotch: ClassVar[Var[Theme]] = construct_theme_var("hopscotch")
350
+ light: ClassVar[Var[Theme]] = construct_theme_var("oneLight")
351
+ lucario: ClassVar[Var[Theme]] = construct_theme_var("lucario")
352
+ material_dark: ClassVar[Var[Theme]] = construct_theme_var("materialDark")
353
+ material_light: ClassVar[Var[Theme]] = construct_theme_var("materialLight")
354
+ material_oceanic: ClassVar[Var[Theme]] = construct_theme_var("materialOceanic")
355
+ night_owl: ClassVar[Var[Theme]] = construct_theme_var("nightOwl")
356
+ nord: ClassVar[Var[Theme]] = construct_theme_var("nord")
357
+ okaidia: ClassVar[Var[Theme]] = construct_theme_var("okaidia")
358
+ one_dark: ClassVar[Var[Theme]] = construct_theme_var("oneDark")
359
+ one_light: ClassVar[Var[Theme]] = construct_theme_var("oneLight")
360
+ pojoaque: ClassVar[Var[Theme]] = construct_theme_var("pojoaque")
361
+ prism: ClassVar[Var[Theme]] = construct_theme_var("prism")
362
+ shades_of_purple: ClassVar[Var[Theme]] = construct_theme_var("shadesOfPurple")
363
+ solarized_dark_atom: ClassVar[Var[Theme]] = construct_theme_var("solarizedDarkAtom")
364
+ solarizedlight: ClassVar[Var[Theme]] = construct_theme_var("solarizedlight")
365
+ synthwave84: ClassVar[Var[Theme]] = construct_theme_var("synthwave84")
366
+ tomorrow: ClassVar[Var[Theme]] = construct_theme_var("tomorrow")
367
+ twilight: ClassVar[Var[Theme]] = construct_theme_var("twilight")
368
+ vs: ClassVar[Var[Theme]] = construct_theme_var("vs")
369
+ vs_dark: ClassVar[Var[Theme]] = construct_theme_var("vsDark")
370
+ vsc_dark_plus: ClassVar[Var[Theme]] = construct_theme_var("vscDarkPlus")
371
+ xonokai: ClassVar[Var[Theme]] = construct_theme_var("xonokai")
372
+ z_touch: ClassVar[Var[Theme]] = construct_theme_var("zTouch")
373
+
374
+
375
+ for theme_name in dir(Theme):
376
+ if theme_name.startswith("_"):
377
+ continue
378
+ setattr(Theme, theme_name, getattr(Theme, theme_name)._replace(_var_type=Theme))
379
+
380
+
381
+ class CodeBlock(Component, MarkdownComponentMap):
382
+ """A code block."""
383
+
384
+ library = "react-syntax-highlighter@16.1.1"
385
+
386
+ tag = "PrismAsyncLight"
387
+
388
+ alias = "SyntaxHighlighter"
389
+
390
+ theme: Var[Theme | str] = field(
391
+ default=Theme.one_light, doc='The theme to use ("light" or "dark").'
392
+ )
393
+
394
+ language: Var[LiteralCodeLanguage] = field(
395
+ default=Var.create("python"), doc="The language to use."
396
+ )
397
+
398
+ code: Var[str] = field(doc="The code to display.")
399
+
400
+ show_line_numbers: Var[bool] = field(
401
+ doc="If this is enabled line numbers will be shown next to the code block."
402
+ )
403
+
404
+ starting_line_number: Var[int] = field(doc="The starting line number to use.")
405
+
406
+ wrap_long_lines: Var[bool] = field(doc="Whether to wrap long lines.")
407
+
408
+ custom_style: dict[str, str | Var | Color] = field(
409
+ doc="A custom style for the code block.",
410
+ default_factory=dict,
411
+ is_javascript_property=False,
412
+ )
413
+
414
+ code_tag_props: Var[dict[str, str | dict[str, str]]] = field(
415
+ doc="Props passed down to the code tag."
416
+ )
417
+
418
+ # Whether a copy button should appear.
419
+ can_copy: bool | None = field(
420
+ default=False,
421
+ is_javascript_property=False,
422
+ )
423
+
424
+ # A custom copy button to override the default one.
425
+ copy_button: bool | Component | None = field(
426
+ default=None,
427
+ is_javascript_property=False,
428
+ )
429
+
430
+ @classmethod
431
+ def create(
432
+ cls,
433
+ *children,
434
+ **props,
435
+ ):
436
+ """Create a text component.
437
+
438
+ Args:
439
+ *children: The children of the component.
440
+ **props: The props to pass to the component.
441
+
442
+ Returns:
443
+ The text component.
444
+ """
445
+ from reflex_components_lucide.icon import Icon
446
+
447
+ # This component handles style in a special prop.
448
+ custom_style = props.pop("custom_style", {})
449
+ can_copy = props.pop("can_copy", False)
450
+ copy_button = props.pop("copy_button", None)
451
+
452
+ # react-syntax-highlighter doesn't have an explicit "light" or "dark" theme so we use one-light and one-dark
453
+ # themes respectively to ensure code compatibility.
454
+ if "theme" not in props:
455
+ # Default color scheme responds to global color mode.
456
+ props["theme"] = color_mode_cond(
457
+ light=Theme.one_light,
458
+ dark=Theme.one_dark,
459
+ )
460
+
461
+ if can_copy:
462
+ code = children[0]
463
+ copy_button = (
464
+ copy_button
465
+ if copy_button is not None
466
+ else Button.create(
467
+ Icon.create(tag="copy"),
468
+ on_click=set_clipboard(code),
469
+ style=Style({"position": "absolute", "top": "0.5em", "right": "0"}),
470
+ )
471
+ )
472
+ custom_style.update({"padding": "1em 3.2em 1em 1em"})
473
+ else:
474
+ copy_button = None
475
+
476
+ # Transfer style props to the custom style prop.
477
+ for key, value in props.items():
478
+ if key not in cls.get_fields():
479
+ custom_style[key] = value
480
+
481
+ # Carry the children (code) via props
482
+ if children:
483
+ props["code"] = children[0]
484
+ if not isinstance(props["code"], Var):
485
+ props["code"] = LiteralVar.create(props["code"])
486
+
487
+ # Create the component.
488
+ code_block = super().create(
489
+ **props,
490
+ custom_style=Style(custom_style),
491
+ )
492
+
493
+ if copy_button:
494
+ return Box.create(code_block, copy_button, position="relative")
495
+ return code_block
496
+
497
+ def add_style(self):
498
+ """Add style to the component."""
499
+ self.custom_style.update(self.style)
500
+
501
+ def _render(self):
502
+ out = super()._render()
503
+
504
+ theme = self.theme
505
+
506
+ return (
507
+ out
508
+ .add_props(style=theme)
509
+ .remove_props("theme", "code")
510
+ .add_props(
511
+ children=self.code,
512
+ )
513
+ )
514
+
515
+
516
+ class CodeblockNamespace(ComponentNamespace):
517
+ """Namespace for the CodeBlock component."""
518
+
519
+ themes = Theme
520
+
521
+ __call__ = CodeBlock.create
522
+
523
+
524
+ code_block = CodeblockNamespace()