Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: icon type auto-generation and normalization #696

Merged
merged 11 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion plugins/ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,15 @@ python make_docs.py
```

The files will be built into `docs/build/markdown`.
Note that these built files should not be committed to the repository.
Note that these built files should not be committed to the repository.

## Update Icon Types
Available IconTypes can be generated automatically using icon TypeScript definitions in node_modules.

Writes to `icon_types.py`.

```shell
npm install
ethanalvizo marked this conversation as resolved.
Show resolved Hide resolved
cd plugins/ui
python make_icon_types.py
```
67 changes: 67 additions & 0 deletions plugins/ui/make_icon_types.py
ethanalvizo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import re
from typing import Dict, Any


def camel_to_snake(name: str) -> str:
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()


relative_path = "./src/js/node_modules/@deephaven/icons/dist/index.d.ts"
icon_pattern = r"^export const (\w+): IconDefinition;$"

icons = {}
snakeCase = {}
noPrefix = {}
snakeCaseNoPrefix = {}

with open(relative_path, "r") as file:
for line in file:
match = re.match(icon_pattern, line)
if match:
icon = line.split(" ")[2].strip()[:-1]
if icon != "IconDefinition":
icons[icon] = icon
snakeCase[camel_to_snake(icon)] = icon

isVsIcon = icon.startswith("vs")
noPrefixIcon = icon[2:]
snakeCaseNoPrefixIcon = camel_to_snake(noPrefixIcon)

## DH Icons are always prefixed with "dh"
if isVsIcon:
noPrefix[noPrefixIcon] = icon
snakeCaseNoPrefix[snakeCaseNoPrefixIcon] = icon

output_file_path = "./src/deephaven/ui/components/types/icon_types.py"

with open(output_file_path, "w") as output_file:
output_file.truncate(0)

output_file.write(
"from __future__ import annotations\n" + "from typing import Literal\n\n"
)

## IconTypes
output_file.write("IconTypes = Literal[\n")
for key, value in snakeCaseNoPrefix.items():
output_file.write(' "' + key + '",' + "\n")
for key, value in snakeCase.items():
if key.startswith("dh"):
output_file.write(' "' + key + '",' + "\n")
output_file.write("]" + "\n")

## IconMapping
output_file.write("\n")
output_file.write("IconMapping = {" + "\n")
for dict in [icons, noPrefix, snakeCase, snakeCaseNoPrefix]:
for key, value in dict.items():
output_file.write(' "' + key + '": "' + value + '",' + "\n")
output_file.write("}" + "\n")


print(f"Generated file: {output_file_path}")
print(f"Total number of icon types: {len(snakeCaseNoPrefix)}")
print(
f"Total number of icon mappings: {len(icons) + len(noPrefix) + len(snakeCase) + len(snakeCaseNoPrefix)}"
)
7 changes: 5 additions & 2 deletions plugins/ui/src/deephaven/ui/components/icon.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
Position,
IconSize,
IconColor,
IconTypes,
IconMapping,
)
from .._internal.utils import create_props


def icon(
name: str,
name: IconTypes,
size: IconSize | None = None,
color: IconColor | None = None,
flex: LayoutFlex | None = None,
Expand Down Expand Up @@ -114,4 +116,5 @@ def icon(
"""

children, props = create_props(locals())
return BaseElement(f"deephaven.ui.icons.{name}", *children, **props)
normalized_name = IconMapping[name]
return BaseElement(f"deephaven.ui.icons.{normalized_name}", *children, **props)
6 changes: 3 additions & 3 deletions plugins/ui/src/deephaven/ui/components/text_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
NecessityIndicator,
)

from ..types import Icon
from .types import IconTypes
from .basic import component_element
from ..elements import Element

from .icon import icon as icon_component


def text_area(
icon: Element | Icon | None = None,
icon: Element | IconTypes | None = None,
is_quiet: bool | None = None,
is_disabled: bool | None = None,
is_read_only: bool | None = None,
Expand Down Expand Up @@ -193,7 +193,7 @@ def text_area(

return component_element(
"TextArea",
icon=icon_component(icon) if type(icon) == str else icon,
icon=icon_component(name=icon) if type(icon) == str else icon,
is_quiet=is_quiet,
is_disabled=is_disabled,
is_read_only=is_read_only,
Expand Down
1 change: 1 addition & 0 deletions plugins/ui/src/deephaven/ui/components/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from .events import *
from .layout import *
from .validate import *
from .icon_types import *
Loading
Loading