Compare commits
59 Commits
symfony_3
...
v2026.2.0-
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d6aff8d90 | |||
| 15ba26ccf2 | |||
| d3fa0cbbf9 | |||
| ed776ca75b | |||
| 67133a4efa | |||
| 6044ee5c50 | |||
| 184925ab13 | |||
| 5a5467fda9 | |||
| f135746826 | |||
| 62915fe5e4 | |||
| 68a25aafa4 | |||
| 9fff5bd5d1 | |||
| 304663adb7 | |||
| cd593e99fc | |||
| 9d51654aec | |||
| 82465322f2 | |||
| 055e59d896 | |||
| 3db8a30115 | |||
| 2e8d878337 | |||
| 28221e092a | |||
| 0c0b8ae920 | |||
| 98f6e8cb6e | |||
| 4239177563 | |||
| e9c6795eb7 | |||
| fb8a54f687 | |||
| 0144a3953c | |||
| acbe9c7f63 | |||
| e2b227ed7a | |||
| c0dcc2896a | |||
| 92bfa5b301 | |||
| 826690769f | |||
| 6b3e19b063 | |||
| eff849549b | |||
| 63a0f442ed | |||
| 1cf21622b8 | |||
| 85a440017c | |||
| d388e25192 | |||
| 5b55a6ce73 | |||
| c660c13ea2 | |||
| d186a96f0d | |||
| b57442bec1 | |||
| 086d6c601e | |||
| 15806a6e04 | |||
| fe2de91e91 | |||
| 76143fca3e | |||
| 7219471a86 | |||
| b55c223d8a | |||
| 23547f4237 | |||
| 4cdca43ecc | |||
| fa0fc0743d | |||
| dd4b410624 | |||
| 1b5e87c033 | |||
| 2daab7140e | |||
| 8355cc90ed | |||
| c909c036a3 | |||
| 3bbc96c76c | |||
| 6caf340302 | |||
| 98b71d75e9 | |||
| aae8b9ebec |
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
node_modules
|
||||||
|
var/cache
|
||||||
|
var/log
|
||||||
|
var/sessions
|
||||||
|
public/build
|
||||||
|
*.md
|
||||||
|
docker-compose*.yml
|
||||||
|
compose.override.yaml
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
884
.editorconfig
Normal file
884
.editorconfig
Normal file
@@ -0,0 +1,884 @@
|
|||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
max_line_length = 120
|
||||||
|
tab_width = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
ij_continuation_indent_size = 8
|
||||||
|
ij_formatter_off_tag = @formatter:off
|
||||||
|
ij_formatter_on_tag = @formatter:on
|
||||||
|
ij_formatter_tags_enabled = true
|
||||||
|
ij_smart_tabs = false
|
||||||
|
ij_visual_guides = 80,120
|
||||||
|
ij_wrap_on_typing = false
|
||||||
|
|
||||||
|
[*.blade.php]
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_blade_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
|
[*.css]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_css_align_closing_brace_with_properties = false
|
||||||
|
ij_css_blank_lines_around_nested_selector = 1
|
||||||
|
ij_css_blank_lines_between_blocks = 1
|
||||||
|
ij_css_block_comment_add_space = false
|
||||||
|
ij_css_brace_placement = end_of_line
|
||||||
|
ij_css_enforce_quotes_on_format = false
|
||||||
|
ij_css_hex_color_long_format = false
|
||||||
|
ij_css_hex_color_lower_case = false
|
||||||
|
ij_css_hex_color_short_format = false
|
||||||
|
ij_css_hex_color_upper_case = false
|
||||||
|
ij_css_keep_blank_lines_in_code = 2
|
||||||
|
ij_css_keep_indents_on_empty_lines = false
|
||||||
|
ij_css_keep_single_line_blocks = false
|
||||||
|
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_css_space_after_colon = true
|
||||||
|
ij_css_space_before_opening_brace = true
|
||||||
|
ij_css_use_double_quotes = true
|
||||||
|
ij_css_value_alignment = do_not_align
|
||||||
|
|
||||||
|
[*.feature]
|
||||||
|
indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_gherkin_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
|
[*.less]
|
||||||
|
indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_less_align_closing_brace_with_properties = false
|
||||||
|
ij_less_blank_lines_around_nested_selector = 1
|
||||||
|
ij_less_blank_lines_between_blocks = 1
|
||||||
|
ij_less_block_comment_add_space = false
|
||||||
|
ij_less_brace_placement = 0
|
||||||
|
ij_less_enforce_quotes_on_format = false
|
||||||
|
ij_less_hex_color_long_format = false
|
||||||
|
ij_less_hex_color_lower_case = false
|
||||||
|
ij_less_hex_color_short_format = false
|
||||||
|
ij_less_hex_color_upper_case = false
|
||||||
|
ij_less_keep_blank_lines_in_code = 2
|
||||||
|
ij_less_keep_indents_on_empty_lines = false
|
||||||
|
ij_less_keep_single_line_blocks = false
|
||||||
|
ij_less_line_comment_add_space = false
|
||||||
|
ij_less_line_comment_at_first_column = false
|
||||||
|
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_less_space_after_colon = true
|
||||||
|
ij_less_space_before_opening_brace = true
|
||||||
|
ij_less_use_double_quotes = true
|
||||||
|
ij_less_value_alignment = 0
|
||||||
|
|
||||||
|
[*.neon]
|
||||||
|
ij_visual_guides =
|
||||||
|
|
||||||
|
[*.sass]
|
||||||
|
indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_sass_align_closing_brace_with_properties = false
|
||||||
|
ij_sass_blank_lines_around_nested_selector = 1
|
||||||
|
ij_sass_blank_lines_between_blocks = 1
|
||||||
|
ij_sass_brace_placement = 0
|
||||||
|
ij_sass_enforce_quotes_on_format = false
|
||||||
|
ij_sass_hex_color_long_format = false
|
||||||
|
ij_sass_hex_color_lower_case = false
|
||||||
|
ij_sass_hex_color_short_format = false
|
||||||
|
ij_sass_hex_color_upper_case = false
|
||||||
|
ij_sass_keep_blank_lines_in_code = 2
|
||||||
|
ij_sass_keep_indents_on_empty_lines = false
|
||||||
|
ij_sass_keep_single_line_blocks = false
|
||||||
|
ij_sass_line_comment_add_space = false
|
||||||
|
ij_sass_line_comment_at_first_column = false
|
||||||
|
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_sass_space_after_colon = true
|
||||||
|
ij_sass_space_before_opening_brace = true
|
||||||
|
ij_sass_use_double_quotes = true
|
||||||
|
ij_sass_value_alignment = 0
|
||||||
|
|
||||||
|
[*.scss]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_scss_align_closing_brace_with_properties = false
|
||||||
|
ij_scss_blank_lines_around_nested_selector = 1
|
||||||
|
ij_scss_blank_lines_between_blocks = 1
|
||||||
|
ij_scss_block_comment_add_space = false
|
||||||
|
ij_scss_brace_placement = 0
|
||||||
|
ij_scss_enforce_quotes_on_format = false
|
||||||
|
ij_scss_hex_color_long_format = false
|
||||||
|
ij_scss_hex_color_lower_case = false
|
||||||
|
ij_scss_hex_color_short_format = false
|
||||||
|
ij_scss_hex_color_upper_case = false
|
||||||
|
ij_scss_keep_blank_lines_in_code = 2
|
||||||
|
ij_scss_keep_indents_on_empty_lines = false
|
||||||
|
ij_scss_keep_single_line_blocks = false
|
||||||
|
ij_scss_line_comment_add_space = false
|
||||||
|
ij_scss_line_comment_at_first_column = false
|
||||||
|
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||||
|
ij_scss_space_after_colon = true
|
||||||
|
ij_scss_space_before_opening_brace = true
|
||||||
|
ij_scss_use_double_quotes = true
|
||||||
|
ij_scss_value_alignment = 0
|
||||||
|
|
||||||
|
[*.twig]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_twig_keep_indents_on_empty_lines = false
|
||||||
|
ij_twig_spaces_inside_comments_delimiters = true
|
||||||
|
ij_twig_spaces_inside_delimiters = true
|
||||||
|
ij_twig_spaces_inside_variable_delimiters = true
|
||||||
|
|
||||||
|
[*.vue]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_vue_indent_children_of_top_level = template
|
||||||
|
ij_vue_interpolation_new_line_after_start_delimiter = true
|
||||||
|
ij_vue_interpolation_new_line_before_end_delimiter = true
|
||||||
|
ij_vue_interpolation_wrap = off
|
||||||
|
ij_vue_keep_indents_on_empty_lines = false
|
||||||
|
ij_vue_spaces_within_interpolation_expressions = true
|
||||||
|
|
||||||
|
[.editorconfig]
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_editorconfig_align_group_field_declarations = false
|
||||||
|
ij_editorconfig_space_after_colon = true
|
||||||
|
ij_editorconfig_space_after_comma = true
|
||||||
|
ij_editorconfig_space_before_colon = true
|
||||||
|
ij_editorconfig_space_before_comma = false
|
||||||
|
ij_editorconfig_spaces_around_assignment_operators = true
|
||||||
|
|
||||||
|
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xlf,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_xml_align_attributes = true
|
||||||
|
ij_xml_align_text = false
|
||||||
|
ij_xml_attribute_wrap = normal
|
||||||
|
ij_xml_block_comment_add_space = false
|
||||||
|
ij_xml_block_comment_at_first_column = true
|
||||||
|
ij_xml_keep_blank_lines = 2
|
||||||
|
ij_xml_keep_indents_on_empty_lines = false
|
||||||
|
ij_xml_keep_line_breaks = true
|
||||||
|
ij_xml_keep_line_breaks_in_text = true
|
||||||
|
ij_xml_keep_whitespaces = false
|
||||||
|
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||||
|
ij_xml_keep_whitespaces_inside_cdata = false
|
||||||
|
ij_xml_line_comment_at_first_column = true
|
||||||
|
ij_xml_space_after_tag_name = false
|
||||||
|
ij_xml_space_around_equals_in_attribute = false
|
||||||
|
ij_xml_space_inside_empty_tag = true
|
||||||
|
ij_xml_text_wrap = normal
|
||||||
|
|
||||||
|
[{*.ats,*.cts,*.mts,*.ts,*.tsx}]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_typescript_align_imports = false
|
||||||
|
ij_typescript_align_multiline_array_initializer_expression = false
|
||||||
|
ij_typescript_align_multiline_binary_operation = false
|
||||||
|
ij_typescript_align_multiline_chained_methods = false
|
||||||
|
ij_typescript_align_multiline_extends_list = false
|
||||||
|
ij_typescript_align_multiline_for = true
|
||||||
|
ij_typescript_align_multiline_parameters = true
|
||||||
|
ij_typescript_align_multiline_parameters_in_calls = false
|
||||||
|
ij_typescript_align_multiline_ternary_operation = false
|
||||||
|
ij_typescript_align_object_properties = 0
|
||||||
|
ij_typescript_align_union_types = false
|
||||||
|
ij_typescript_align_var_statements = 0
|
||||||
|
ij_typescript_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_typescript_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_typescript_array_initializer_wrap = off
|
||||||
|
ij_typescript_assignment_wrap = off
|
||||||
|
ij_typescript_binary_operation_sign_on_next_line = false
|
||||||
|
ij_typescript_binary_operation_wrap = off
|
||||||
|
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||||
|
ij_typescript_blank_lines_after_imports = 1
|
||||||
|
ij_typescript_blank_lines_around_class = 1
|
||||||
|
ij_typescript_blank_lines_around_field = 0
|
||||||
|
ij_typescript_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_typescript_blank_lines_around_function = 1
|
||||||
|
ij_typescript_blank_lines_around_method = 1
|
||||||
|
ij_typescript_blank_lines_around_method_in_interface = 1
|
||||||
|
ij_typescript_block_brace_style = end_of_line
|
||||||
|
ij_typescript_block_comment_add_space = false
|
||||||
|
ij_typescript_block_comment_at_first_column = true
|
||||||
|
ij_typescript_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_typescript_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_typescript_call_parameters_wrap = off
|
||||||
|
ij_typescript_catch_on_new_line = false
|
||||||
|
ij_typescript_chained_call_dot_on_new_line = true
|
||||||
|
ij_typescript_class_brace_style = end_of_line
|
||||||
|
ij_typescript_class_decorator_wrap = split_into_lines
|
||||||
|
ij_typescript_class_field_decorator_wrap = off
|
||||||
|
ij_typescript_class_method_decorator_wrap = off
|
||||||
|
ij_typescript_comma_on_new_line = false
|
||||||
|
ij_typescript_do_while_brace_force = never
|
||||||
|
ij_typescript_else_on_new_line = false
|
||||||
|
ij_typescript_enforce_trailing_comma = whenmultiline
|
||||||
|
ij_typescript_enum_constants_wrap = on_every_item
|
||||||
|
ij_typescript_extends_keyword_wrap = off
|
||||||
|
ij_typescript_extends_list_wrap = off
|
||||||
|
ij_typescript_field_prefix = _
|
||||||
|
ij_typescript_file_name_style = relaxed
|
||||||
|
ij_typescript_finally_on_new_line = false
|
||||||
|
ij_typescript_for_brace_force = never
|
||||||
|
ij_typescript_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_typescript_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_typescript_for_statement_wrap = off
|
||||||
|
ij_typescript_force_quote_style = true
|
||||||
|
ij_typescript_force_semicolon_style = true
|
||||||
|
ij_typescript_function_expression_brace_style = end_of_line
|
||||||
|
ij_typescript_function_parameter_decorator_wrap = off
|
||||||
|
ij_typescript_if_brace_force = never
|
||||||
|
ij_typescript_import_merge_members = global
|
||||||
|
ij_typescript_import_prefer_absolute_path = global
|
||||||
|
ij_typescript_import_sort_members = true
|
||||||
|
ij_typescript_import_sort_module_name = false
|
||||||
|
ij_typescript_import_use_node_resolution = true
|
||||||
|
ij_typescript_imports_wrap = on_every_item
|
||||||
|
ij_typescript_indent_case_from_switch = true
|
||||||
|
ij_typescript_indent_chained_calls = true
|
||||||
|
ij_typescript_indent_package_children = 0
|
||||||
|
ij_typescript_jsdoc_include_types = false
|
||||||
|
ij_typescript_jsx_attribute_value = braces
|
||||||
|
ij_typescript_keep_blank_lines_in_code = 2
|
||||||
|
ij_typescript_keep_first_column_comment = true
|
||||||
|
ij_typescript_keep_indents_on_empty_lines = false
|
||||||
|
ij_typescript_keep_line_breaks = true
|
||||||
|
ij_typescript_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_typescript_keep_simple_methods_in_one_line = false
|
||||||
|
ij_typescript_jsx_self_closing_tag = true
|
||||||
|
ij_typescript_line_comment_add_space = true
|
||||||
|
ij_typescript_line_comment_at_first_column = false
|
||||||
|
ij_typescript_method_brace_style = end_of_line
|
||||||
|
ij_typescript_method_call_chain_wrap = off
|
||||||
|
ij_typescript_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_typescript_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_typescript_method_parameters_wrap = off
|
||||||
|
ij_typescript_object_literal_wrap = on_every_item
|
||||||
|
ij_typescript_object_types_wrap = on_every_item
|
||||||
|
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_typescript_place_assignment_sign_on_next_line = false
|
||||||
|
ij_typescript_prefer_as_type_cast = false
|
||||||
|
ij_typescript_prefer_explicit_types_function_expression_returns = false
|
||||||
|
ij_typescript_prefer_explicit_types_function_returns = false
|
||||||
|
ij_typescript_prefer_explicit_types_vars_fields = false
|
||||||
|
ij_typescript_prefer_parameters_wrap = false
|
||||||
|
ij_typescript_property_prefix =
|
||||||
|
ij_typescript_reformat_c_style_comments = false
|
||||||
|
ij_typescript_space_after_colon = true
|
||||||
|
ij_typescript_space_after_comma = true
|
||||||
|
ij_typescript_space_after_dots_in_rest_parameter = false
|
||||||
|
ij_typescript_space_after_generator_mult = true
|
||||||
|
ij_typescript_space_after_property_colon = true
|
||||||
|
ij_typescript_space_after_quest = true
|
||||||
|
ij_typescript_space_after_type_colon = true
|
||||||
|
ij_typescript_space_after_unary_not = false
|
||||||
|
ij_typescript_space_before_async_arrow_lparen = true
|
||||||
|
ij_typescript_space_before_catch_keyword = true
|
||||||
|
ij_typescript_space_before_catch_left_brace = true
|
||||||
|
ij_typescript_space_before_catch_parentheses = true
|
||||||
|
ij_typescript_space_before_class_lbrace = true
|
||||||
|
ij_typescript_space_before_class_left_brace = true
|
||||||
|
ij_typescript_space_before_colon = true
|
||||||
|
ij_typescript_space_before_comma = false
|
||||||
|
ij_typescript_space_before_do_left_brace = true
|
||||||
|
ij_typescript_space_before_else_keyword = true
|
||||||
|
ij_typescript_space_before_else_left_brace = true
|
||||||
|
ij_typescript_space_before_finally_keyword = true
|
||||||
|
ij_typescript_space_before_finally_left_brace = true
|
||||||
|
ij_typescript_space_before_for_left_brace = true
|
||||||
|
ij_typescript_space_before_for_parentheses = true
|
||||||
|
ij_typescript_space_before_for_semicolon = false
|
||||||
|
ij_typescript_space_before_function_left_parenth = false
|
||||||
|
ij_typescript_space_before_generator_mult = false
|
||||||
|
ij_typescript_space_before_if_left_brace = true
|
||||||
|
ij_typescript_space_before_if_parentheses = true
|
||||||
|
ij_typescript_space_before_method_call_parentheses = false
|
||||||
|
ij_typescript_space_before_method_left_brace = true
|
||||||
|
ij_typescript_space_before_method_parentheses = false
|
||||||
|
ij_typescript_space_before_property_colon = false
|
||||||
|
ij_typescript_space_before_quest = true
|
||||||
|
ij_typescript_space_before_switch_left_brace = true
|
||||||
|
ij_typescript_space_before_switch_parentheses = true
|
||||||
|
ij_typescript_space_before_try_left_brace = true
|
||||||
|
ij_typescript_space_before_type_colon = false
|
||||||
|
ij_typescript_space_before_unary_not = false
|
||||||
|
ij_typescript_space_before_while_keyword = true
|
||||||
|
ij_typescript_space_before_while_left_brace = true
|
||||||
|
ij_typescript_space_before_while_parentheses = true
|
||||||
|
ij_typescript_spaces_around_additive_operators = true
|
||||||
|
ij_typescript_spaces_around_arrow_function_operator = true
|
||||||
|
ij_typescript_spaces_around_assignment_operators = true
|
||||||
|
ij_typescript_spaces_around_bitwise_operators = true
|
||||||
|
ij_typescript_spaces_around_equality_operators = true
|
||||||
|
ij_typescript_spaces_around_logical_operators = true
|
||||||
|
ij_typescript_spaces_around_multiplicative_operators = true
|
||||||
|
ij_typescript_spaces_around_relational_operators = true
|
||||||
|
ij_typescript_spaces_around_shift_operators = true
|
||||||
|
ij_typescript_spaces_around_unary_operator = false
|
||||||
|
ij_typescript_spaces_within_array_initializer_brackets = true
|
||||||
|
ij_typescript_spaces_within_brackets = false
|
||||||
|
ij_typescript_spaces_within_catch_parentheses = false
|
||||||
|
ij_typescript_spaces_within_for_parentheses = false
|
||||||
|
ij_typescript_spaces_within_if_parentheses = false
|
||||||
|
ij_typescript_spaces_within_imports = true
|
||||||
|
ij_typescript_spaces_within_interpolation_expressions = false
|
||||||
|
ij_typescript_spaces_within_method_call_parentheses = false
|
||||||
|
ij_typescript_spaces_within_method_parentheses = false
|
||||||
|
ij_typescript_spaces_within_object_literal_braces = true
|
||||||
|
ij_typescript_spaces_within_object_type_braces = true
|
||||||
|
ij_typescript_spaces_within_parentheses = false
|
||||||
|
ij_typescript_spaces_within_switch_parentheses = false
|
||||||
|
ij_typescript_spaces_within_type_assertion = false
|
||||||
|
ij_typescript_spaces_within_union_types = true
|
||||||
|
ij_typescript_spaces_within_while_parentheses = false
|
||||||
|
ij_typescript_special_else_if_treatment = true
|
||||||
|
ij_typescript_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_typescript_ternary_operation_wrap = off
|
||||||
|
ij_typescript_union_types_wrap = on_every_item
|
||||||
|
ij_typescript_use_chained_calls_group_indents = false
|
||||||
|
ij_typescript_use_double_quotes = false
|
||||||
|
ij_typescript_use_explicit_js_extension = never
|
||||||
|
ij_typescript_use_import_type = auto
|
||||||
|
ij_typescript_use_path_mapping = always
|
||||||
|
ij_typescript_use_public_modifier = false
|
||||||
|
ij_typescript_use_semicolon_after_statement = true
|
||||||
|
ij_typescript_var_declaration_wrap = normal
|
||||||
|
ij_typescript_while_brace_force = never
|
||||||
|
ij_typescript_while_on_new_line = false
|
||||||
|
ij_typescript_wrap_comments = false
|
||||||
|
|
||||||
|
[{*.bash,*.sh,*.zsh}]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_shell_binary_ops_start_line = false
|
||||||
|
ij_shell_keep_column_alignment_padding = false
|
||||||
|
ij_shell_minify_program = false
|
||||||
|
ij_shell_redirect_followed_by_space = false
|
||||||
|
ij_shell_switch_cases_indented = false
|
||||||
|
ij_shell_use_unix_line_separator = true
|
||||||
|
|
||||||
|
[{*.cjs,*.es6,*.js,*.mjs,*.jsx}]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_javascript_align_imports = false
|
||||||
|
ij_javascript_align_multiline_array_initializer_expression = false
|
||||||
|
ij_javascript_align_multiline_binary_operation = false
|
||||||
|
ij_javascript_align_multiline_chained_methods = false
|
||||||
|
ij_javascript_align_multiline_extends_list = false
|
||||||
|
ij_javascript_align_multiline_for = true
|
||||||
|
ij_javascript_align_multiline_parameters = true
|
||||||
|
ij_javascript_align_multiline_parameters_in_calls = false
|
||||||
|
ij_javascript_align_multiline_ternary_operation = false
|
||||||
|
ij_javascript_align_object_properties = 0
|
||||||
|
ij_javascript_align_union_types = false
|
||||||
|
ij_javascript_align_var_statements = 0
|
||||||
|
ij_javascript_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_javascript_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_javascript_array_initializer_wrap = off
|
||||||
|
ij_javascript_assignment_wrap = off
|
||||||
|
ij_javascript_binary_operation_sign_on_next_line = false
|
||||||
|
ij_javascript_binary_operation_wrap = off
|
||||||
|
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||||
|
ij_javascript_blank_lines_after_imports = 1
|
||||||
|
ij_javascript_blank_lines_around_class = 1
|
||||||
|
ij_javascript_blank_lines_around_field = 0
|
||||||
|
ij_javascript_blank_lines_around_function = 1
|
||||||
|
ij_javascript_blank_lines_around_method = 1
|
||||||
|
ij_javascript_block_brace_style = end_of_line
|
||||||
|
ij_javascript_block_comment_add_space = false
|
||||||
|
ij_javascript_block_comment_at_first_column = true
|
||||||
|
ij_javascript_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_javascript_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_javascript_call_parameters_wrap = off
|
||||||
|
ij_javascript_catch_on_new_line = false
|
||||||
|
ij_javascript_chained_call_dot_on_new_line = true
|
||||||
|
ij_javascript_class_brace_style = end_of_line
|
||||||
|
ij_javascript_class_decorator_wrap = split_into_lines
|
||||||
|
ij_javascript_class_field_decorator_wrap = off
|
||||||
|
ij_javascript_class_method_decorator_wrap = off
|
||||||
|
ij_javascript_comma_on_new_line = false
|
||||||
|
ij_javascript_do_while_brace_force = never
|
||||||
|
ij_javascript_else_on_new_line = false
|
||||||
|
ij_javascript_enforce_trailing_comma = whenmultiline
|
||||||
|
ij_javascript_extends_keyword_wrap = off
|
||||||
|
ij_javascript_extends_list_wrap = off
|
||||||
|
ij_javascript_field_prefix = _
|
||||||
|
ij_javascript_file_name_style = relaxed
|
||||||
|
ij_javascript_finally_on_new_line = false
|
||||||
|
ij_javascript_for_brace_force = never
|
||||||
|
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_javascript_for_statement_wrap = off
|
||||||
|
ij_javascript_force_quote_style = true
|
||||||
|
ij_javascript_force_semicolon_style = true
|
||||||
|
ij_javascript_function_expression_brace_style = end_of_line
|
||||||
|
ij_javascript_function_parameter_decorator_wrap = off
|
||||||
|
ij_javascript_if_brace_force = never
|
||||||
|
ij_javascript_import_merge_members = global
|
||||||
|
ij_javascript_import_prefer_absolute_path = global
|
||||||
|
ij_javascript_import_sort_members = true
|
||||||
|
ij_javascript_import_sort_module_name = false
|
||||||
|
ij_javascript_import_use_node_resolution = true
|
||||||
|
ij_javascript_imports_wrap = on_every_item
|
||||||
|
ij_javascript_indent_case_from_switch = true
|
||||||
|
ij_javascript_indent_chained_calls = true
|
||||||
|
ij_javascript_indent_package_children = 0
|
||||||
|
ij_javascript_jsx_attribute_value = braces
|
||||||
|
ij_javascript_keep_blank_lines_in_code = 2
|
||||||
|
ij_javascript_keep_first_column_comment = true
|
||||||
|
ij_javascript_keep_indents_on_empty_lines = false
|
||||||
|
ij_javascript_keep_line_breaks = true
|
||||||
|
ij_javascript_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_javascript_keep_simple_methods_in_one_line = false
|
||||||
|
ij_javascript_jsx_self_closing_tag = true
|
||||||
|
ij_javascript_line_comment_add_space = true
|
||||||
|
ij_javascript_line_comment_at_first_column = false
|
||||||
|
ij_javascript_method_brace_style = end_of_line
|
||||||
|
ij_javascript_method_call_chain_wrap = off
|
||||||
|
ij_javascript_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_javascript_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_javascript_method_parameters_wrap = off
|
||||||
|
ij_javascript_object_literal_wrap = on_every_item
|
||||||
|
ij_javascript_object_types_wrap = on_every_item
|
||||||
|
ij_javascript_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_javascript_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_javascript_place_assignment_sign_on_next_line = false
|
||||||
|
ij_javascript_prefer_as_type_cast = false
|
||||||
|
ij_javascript_prefer_explicit_types_function_expression_returns = false
|
||||||
|
ij_javascript_prefer_explicit_types_function_returns = false
|
||||||
|
ij_javascript_prefer_explicit_types_vars_fields = false
|
||||||
|
ij_javascript_prefer_parameters_wrap = false
|
||||||
|
ij_javascript_property_prefix =
|
||||||
|
ij_javascript_reformat_c_style_comments = true
|
||||||
|
ij_javascript_space_after_colon = true
|
||||||
|
ij_javascript_space_after_comma = true
|
||||||
|
ij_javascript_space_after_dots_in_rest_parameter = false
|
||||||
|
ij_javascript_space_after_generator_mult = true
|
||||||
|
ij_javascript_space_after_property_colon = true
|
||||||
|
ij_javascript_space_after_quest = true
|
||||||
|
ij_javascript_space_after_type_colon = true
|
||||||
|
ij_javascript_space_after_unary_not = false
|
||||||
|
ij_javascript_space_before_async_arrow_lparen = true
|
||||||
|
ij_javascript_space_before_catch_keyword = true
|
||||||
|
ij_javascript_space_before_catch_left_brace = true
|
||||||
|
ij_javascript_space_before_catch_parentheses = true
|
||||||
|
ij_javascript_space_before_class_lbrace = true
|
||||||
|
ij_javascript_space_before_class_left_brace = true
|
||||||
|
ij_javascript_space_before_colon = true
|
||||||
|
ij_javascript_space_before_comma = false
|
||||||
|
ij_javascript_space_before_do_left_brace = true
|
||||||
|
ij_javascript_space_before_else_keyword = true
|
||||||
|
ij_javascript_space_before_else_left_brace = true
|
||||||
|
ij_javascript_space_before_finally_keyword = true
|
||||||
|
ij_javascript_space_before_finally_left_brace = true
|
||||||
|
ij_javascript_space_before_for_left_brace = true
|
||||||
|
ij_javascript_space_before_for_parentheses = true
|
||||||
|
ij_javascript_space_before_for_semicolon = false
|
||||||
|
ij_javascript_space_before_function_left_parenth = false
|
||||||
|
ij_javascript_space_before_generator_mult = false
|
||||||
|
ij_javascript_space_before_if_left_brace = true
|
||||||
|
ij_javascript_space_before_if_parentheses = true
|
||||||
|
ij_javascript_space_before_method_call_parentheses = false
|
||||||
|
ij_javascript_space_before_method_left_brace = true
|
||||||
|
ij_javascript_space_before_method_parentheses = false
|
||||||
|
ij_javascript_space_before_property_colon = false
|
||||||
|
ij_javascript_space_before_quest = true
|
||||||
|
ij_javascript_space_before_switch_left_brace = true
|
||||||
|
ij_javascript_space_before_switch_parentheses = true
|
||||||
|
ij_javascript_space_before_try_left_brace = true
|
||||||
|
ij_javascript_space_before_type_colon = false
|
||||||
|
ij_javascript_space_before_unary_not = false
|
||||||
|
ij_javascript_space_before_while_keyword = true
|
||||||
|
ij_javascript_space_before_while_left_brace = true
|
||||||
|
ij_javascript_space_before_while_parentheses = true
|
||||||
|
ij_javascript_spaces_around_additive_operators = true
|
||||||
|
ij_javascript_spaces_around_arrow_function_operator = true
|
||||||
|
ij_javascript_spaces_around_assignment_operators = true
|
||||||
|
ij_javascript_spaces_around_bitwise_operators = true
|
||||||
|
ij_javascript_spaces_around_equality_operators = true
|
||||||
|
ij_javascript_spaces_around_logical_operators = true
|
||||||
|
ij_javascript_spaces_around_multiplicative_operators = true
|
||||||
|
ij_javascript_spaces_around_relational_operators = true
|
||||||
|
ij_javascript_spaces_around_shift_operators = true
|
||||||
|
ij_javascript_spaces_around_unary_operator = false
|
||||||
|
ij_javascript_spaces_within_array_initializer_brackets = false
|
||||||
|
ij_javascript_spaces_within_brackets = false
|
||||||
|
ij_javascript_spaces_within_catch_parentheses = false
|
||||||
|
ij_javascript_spaces_within_for_parentheses = false
|
||||||
|
ij_javascript_spaces_within_if_parentheses = false
|
||||||
|
ij_javascript_spaces_within_imports = true
|
||||||
|
ij_javascript_spaces_within_interpolation_expressions = false
|
||||||
|
ij_javascript_spaces_within_method_call_parentheses = false
|
||||||
|
ij_javascript_spaces_within_method_parentheses = false
|
||||||
|
ij_javascript_spaces_within_object_literal_braces = true
|
||||||
|
ij_javascript_spaces_within_object_type_braces = true
|
||||||
|
ij_javascript_spaces_within_parentheses = false
|
||||||
|
ij_javascript_spaces_within_switch_parentheses = false
|
||||||
|
ij_javascript_spaces_within_type_assertion = false
|
||||||
|
ij_javascript_spaces_within_union_types = true
|
||||||
|
ij_javascript_spaces_within_while_parentheses = false
|
||||||
|
ij_javascript_special_else_if_treatment = true
|
||||||
|
ij_javascript_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_javascript_ternary_operation_wrap = off
|
||||||
|
ij_javascript_union_types_wrap = on_every_item
|
||||||
|
ij_javascript_use_chained_calls_group_indents = false
|
||||||
|
ij_javascript_use_double_quotes = false
|
||||||
|
ij_javascript_use_explicit_js_extension = never
|
||||||
|
ij_javascript_use_import_type = auto
|
||||||
|
ij_javascript_use_path_mapping = always
|
||||||
|
ij_javascript_use_public_modifier = false
|
||||||
|
ij_javascript_use_semicolon_after_statement = true
|
||||||
|
ij_javascript_var_declaration_wrap = normal
|
||||||
|
ij_javascript_while_brace_force = never
|
||||||
|
ij_javascript_while_on_new_line = false
|
||||||
|
ij_javascript_wrap_comments = true
|
||||||
|
|
||||||
|
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_php_align_assignments = false
|
||||||
|
ij_php_align_class_constants = true
|
||||||
|
ij_php_align_enum_cases = false
|
||||||
|
ij_php_align_group_field_declarations = false
|
||||||
|
ij_php_align_inline_comments = false
|
||||||
|
ij_php_align_key_value_pairs = true
|
||||||
|
ij_php_align_match_arm_bodies = true
|
||||||
|
ij_php_align_multiline_array_initializer_expression = false
|
||||||
|
ij_php_align_multiline_binary_operation = false
|
||||||
|
ij_php_align_multiline_chained_methods = true
|
||||||
|
ij_php_align_multiline_extends_list = false
|
||||||
|
ij_php_align_multiline_for = true
|
||||||
|
ij_php_align_multiline_parameters = true
|
||||||
|
ij_php_align_multiline_parameters_in_calls = false
|
||||||
|
ij_php_align_multiline_ternary_operation = false
|
||||||
|
ij_php_align_named_arguments = false
|
||||||
|
ij_php_align_phpdoc_comments = true
|
||||||
|
ij_php_align_phpdoc_param_names = true
|
||||||
|
ij_php_anonymous_brace_style = end_of_line
|
||||||
|
ij_php_api_weight = 28
|
||||||
|
ij_php_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_php_array_initializer_right_brace_on_new_line = true
|
||||||
|
ij_php_array_initializer_wrap = off
|
||||||
|
ij_php_assignment_wrap = off
|
||||||
|
ij_php_attributes_wrap = off
|
||||||
|
ij_php_author_weight = 1
|
||||||
|
ij_php_binary_operation_sign_on_next_line = false
|
||||||
|
ij_php_binary_operation_wrap = off
|
||||||
|
ij_php_blank_lines_after_class_header = 0
|
||||||
|
ij_php_blank_lines_after_function = 1
|
||||||
|
ij_php_blank_lines_after_imports = 1
|
||||||
|
ij_php_blank_lines_after_opening_tag = 0
|
||||||
|
ij_php_blank_lines_after_package = 0
|
||||||
|
ij_php_blank_lines_around_class = 1
|
||||||
|
ij_php_blank_lines_around_constants = 0
|
||||||
|
ij_php_blank_lines_around_enum_cases = 0
|
||||||
|
ij_php_blank_lines_around_field = 1
|
||||||
|
ij_php_blank_lines_around_method = 1
|
||||||
|
ij_php_blank_lines_before_class_end = 0
|
||||||
|
ij_php_blank_lines_before_imports = 1
|
||||||
|
ij_php_blank_lines_before_method_body = 0
|
||||||
|
ij_php_blank_lines_before_package = 1
|
||||||
|
ij_php_blank_lines_before_return_statement = 0
|
||||||
|
ij_php_blank_lines_between_imports = 0
|
||||||
|
ij_php_block_brace_style = end_of_line
|
||||||
|
ij_php_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_php_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_php_call_parameters_wrap = off
|
||||||
|
ij_php_catch_on_new_line = false
|
||||||
|
ij_php_category_weight = 28
|
||||||
|
ij_php_class_brace_style = next_line
|
||||||
|
ij_php_comma_after_last_argument = false
|
||||||
|
ij_php_comma_after_last_argument_style = when_multiline
|
||||||
|
ij_php_comma_after_last_array_element = true
|
||||||
|
ij_php_comma_after_last_closure_use_var = false
|
||||||
|
ij_php_comma_after_last_closure_use_var_style = when_multiline
|
||||||
|
ij_php_comma_after_last_match_arm = false
|
||||||
|
ij_php_comma_after_last_parameter = false
|
||||||
|
ij_php_comma_after_last_parameter_style = when_multiline
|
||||||
|
ij_php_concat_spaces = true
|
||||||
|
ij_php_copyright_weight = 28
|
||||||
|
ij_php_deprecated_weight = 28
|
||||||
|
ij_php_do_while_brace_force = never
|
||||||
|
ij_php_else_if_style = as_is
|
||||||
|
ij_php_else_on_new_line = false
|
||||||
|
ij_php_example_weight = 28
|
||||||
|
ij_php_extends_keyword_wrap = off
|
||||||
|
ij_php_extends_list_wrap = off
|
||||||
|
ij_php_fields_default_visibility = private
|
||||||
|
ij_php_filesource_weight = 28
|
||||||
|
ij_php_finally_on_new_line = false
|
||||||
|
ij_php_for_brace_force = never
|
||||||
|
ij_php_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_php_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_php_for_statement_wrap = off
|
||||||
|
ij_php_force_empty_classes_in_one_line = false
|
||||||
|
ij_php_force_empty_methods_in_one_line = false
|
||||||
|
ij_php_force_short_declaration_array_style = false
|
||||||
|
ij_php_getters_setters_naming_style = camel_case
|
||||||
|
ij_php_getters_setters_order_style = getters_first
|
||||||
|
ij_php_global_weight = 28
|
||||||
|
ij_php_group_use_wrap = on_every_item
|
||||||
|
ij_php_heredoc_on_same_line = false
|
||||||
|
ij_php_if_brace_force = never
|
||||||
|
ij_php_if_lparen_on_next_line = false
|
||||||
|
ij_php_if_rparen_on_next_line = false
|
||||||
|
ij_php_ignore_weight = 28
|
||||||
|
ij_php_import_sorting = alphabetic
|
||||||
|
ij_php_indent_break_from_case = true
|
||||||
|
ij_php_indent_case_from_switch = true
|
||||||
|
ij_php_indent_code_in_php_tags = false
|
||||||
|
ij_php_internal_weight = 28
|
||||||
|
ij_php_keep_blank_lines_after_lbrace = 2
|
||||||
|
ij_php_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_php_keep_blank_lines_in_code = 2
|
||||||
|
ij_php_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_php_keep_control_statement_in_one_line = true
|
||||||
|
ij_php_keep_first_column_comment = false
|
||||||
|
ij_php_keep_indents_on_empty_lines = false
|
||||||
|
ij_php_keep_line_breaks = true
|
||||||
|
ij_php_keep_rparen_and_lbrace_on_one_line = true
|
||||||
|
ij_php_keep_simple_classes_in_one_line = true
|
||||||
|
ij_php_keep_simple_methods_in_one_line = true
|
||||||
|
ij_php_lambda_brace_style = end_of_line
|
||||||
|
ij_php_license_weight = 28
|
||||||
|
ij_php_line_comment_add_space = false
|
||||||
|
ij_php_line_comment_at_first_column = true
|
||||||
|
ij_php_link_weight = 28
|
||||||
|
ij_php_lower_case_boolean_const = true
|
||||||
|
ij_php_lower_case_keywords = true
|
||||||
|
ij_php_lower_case_null_const = true
|
||||||
|
ij_php_method_brace_style = next_line
|
||||||
|
ij_php_method_call_chain_wrap = normal
|
||||||
|
ij_php_method_parameters_new_line_after_left_paren = true
|
||||||
|
ij_php_method_parameters_right_paren_on_new_line = true
|
||||||
|
ij_php_method_parameters_wrap = on_every_item
|
||||||
|
ij_php_method_weight = 5
|
||||||
|
ij_php_modifier_list_wrap = false
|
||||||
|
ij_php_multiline_chained_calls_first_call_on_new_line = false
|
||||||
|
ij_php_multiline_chained_calls_semicolon_on_new_line = false
|
||||||
|
ij_php_multiline_closure_lambda_on_new_line = false
|
||||||
|
ij_php_namespace_brace_style = 2
|
||||||
|
ij_php_new_line_after_php_opening_tag = false
|
||||||
|
ij_php_null_type_position = in_the_end
|
||||||
|
ij_php_package_weight = 0
|
||||||
|
ij_php_param_weight = 2
|
||||||
|
ij_php_parameters_attributes_wrap = off
|
||||||
|
ij_php_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_php_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_php_phpdoc_blank_line_before_tags = true
|
||||||
|
ij_php_phpdoc_blank_lines_around_parameters = true
|
||||||
|
ij_php_phpdoc_keep_blank_lines = true
|
||||||
|
ij_php_phpdoc_param_spaces_between_name_and_description = 1
|
||||||
|
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
|
||||||
|
ij_php_phpdoc_param_spaces_between_type_and_name = 1
|
||||||
|
ij_php_phpdoc_use_fqcn = false
|
||||||
|
ij_php_phpdoc_wrap_long_lines = true
|
||||||
|
ij_php_place_assignment_sign_on_next_line = false
|
||||||
|
ij_php_place_parens_for_constructor = 0
|
||||||
|
ij_php_property_read_weight = 28
|
||||||
|
ij_php_property_weight = 28
|
||||||
|
ij_php_property_write_weight = 28
|
||||||
|
ij_php_return_type_on_new_line = false
|
||||||
|
ij_php_return_weight = 3
|
||||||
|
ij_php_see_weight = 28
|
||||||
|
ij_php_since_weight = 28
|
||||||
|
ij_php_sort_phpdoc_elements = true
|
||||||
|
ij_php_space_after_colon = true
|
||||||
|
ij_php_space_after_colon_in_enum_backed_type = true
|
||||||
|
ij_php_space_after_colon_in_named_argument = true
|
||||||
|
ij_php_space_after_colon_in_return_type = true
|
||||||
|
ij_php_space_after_comma = true
|
||||||
|
ij_php_space_after_for_semicolon = true
|
||||||
|
ij_php_space_after_quest = true
|
||||||
|
ij_php_space_after_type_cast = false
|
||||||
|
ij_php_space_after_unary_not = false
|
||||||
|
ij_php_space_before_array_initializer_left_brace = false
|
||||||
|
ij_php_space_before_catch_keyword = true
|
||||||
|
ij_php_space_before_catch_left_brace = true
|
||||||
|
ij_php_space_before_catch_parentheses = true
|
||||||
|
ij_php_space_before_class_left_brace = true
|
||||||
|
ij_php_space_before_closure_left_parenthesis = true
|
||||||
|
ij_php_space_before_colon = true
|
||||||
|
ij_php_space_before_colon_in_enum_backed_type = false
|
||||||
|
ij_php_space_before_colon_in_named_argument = false
|
||||||
|
ij_php_space_before_colon_in_return_type = false
|
||||||
|
ij_php_space_before_comma = false
|
||||||
|
ij_php_space_before_do_left_brace = true
|
||||||
|
ij_php_space_before_else_keyword = true
|
||||||
|
ij_php_space_before_else_left_brace = true
|
||||||
|
ij_php_space_before_finally_keyword = true
|
||||||
|
ij_php_space_before_finally_left_brace = true
|
||||||
|
ij_php_space_before_for_left_brace = true
|
||||||
|
ij_php_space_before_for_parentheses = true
|
||||||
|
ij_php_space_before_for_semicolon = false
|
||||||
|
ij_php_space_before_if_left_brace = true
|
||||||
|
ij_php_space_before_if_parentheses = true
|
||||||
|
ij_php_space_before_method_call_parentheses = false
|
||||||
|
ij_php_space_before_method_left_brace = true
|
||||||
|
ij_php_space_before_method_parentheses = false
|
||||||
|
ij_php_space_before_quest = true
|
||||||
|
ij_php_space_before_short_closure_left_parenthesis = false
|
||||||
|
ij_php_space_before_switch_left_brace = true
|
||||||
|
ij_php_space_before_switch_parentheses = true
|
||||||
|
ij_php_space_before_try_left_brace = true
|
||||||
|
ij_php_space_before_unary_not = false
|
||||||
|
ij_php_space_before_while_keyword = true
|
||||||
|
ij_php_space_before_while_left_brace = true
|
||||||
|
ij_php_space_before_while_parentheses = true
|
||||||
|
ij_php_space_between_ternary_quest_and_colon = false
|
||||||
|
ij_php_spaces_around_additive_operators = true
|
||||||
|
ij_php_spaces_around_arrow = false
|
||||||
|
ij_php_spaces_around_assignment_in_declare = false
|
||||||
|
ij_php_spaces_around_assignment_operators = true
|
||||||
|
ij_php_spaces_around_bitwise_operators = true
|
||||||
|
ij_php_spaces_around_equality_operators = true
|
||||||
|
ij_php_spaces_around_logical_operators = true
|
||||||
|
ij_php_spaces_around_multiplicative_operators = true
|
||||||
|
ij_php_spaces_around_null_coalesce_operator = true
|
||||||
|
ij_php_spaces_around_pipe_in_union_type = false
|
||||||
|
ij_php_spaces_around_relational_operators = true
|
||||||
|
ij_php_spaces_around_shift_operators = true
|
||||||
|
ij_php_spaces_around_unary_operator = false
|
||||||
|
ij_php_spaces_around_var_within_brackets = false
|
||||||
|
ij_php_spaces_within_array_initializer_braces = false
|
||||||
|
ij_php_spaces_within_brackets = false
|
||||||
|
ij_php_spaces_within_catch_parentheses = false
|
||||||
|
ij_php_spaces_within_for_parentheses = false
|
||||||
|
ij_php_spaces_within_if_parentheses = false
|
||||||
|
ij_php_spaces_within_method_call_parentheses = false
|
||||||
|
ij_php_spaces_within_method_parentheses = false
|
||||||
|
ij_php_spaces_within_parentheses = false
|
||||||
|
ij_php_spaces_within_short_echo_tags = true
|
||||||
|
ij_php_spaces_within_switch_parentheses = false
|
||||||
|
ij_php_spaces_within_while_parentheses = false
|
||||||
|
ij_php_special_else_if_treatment = false
|
||||||
|
ij_php_subpackage_weight = 28
|
||||||
|
ij_php_ternary_operation_signs_on_next_line = true
|
||||||
|
ij_php_ternary_operation_wrap = off
|
||||||
|
ij_php_throws_weight = 4
|
||||||
|
ij_php_todo_weight = 28
|
||||||
|
ij_php_treat_multiline_arrays_and_lambdas_multiline = false
|
||||||
|
ij_php_unknown_tag_weight = 28
|
||||||
|
ij_php_upper_case_boolean_const = false
|
||||||
|
ij_php_upper_case_null_const = false
|
||||||
|
ij_php_uses_weight = 28
|
||||||
|
ij_php_var_weight = 28
|
||||||
|
ij_php_variable_naming_style = mixed
|
||||||
|
ij_php_version_weight = 28
|
||||||
|
ij_php_while_brace_force = never
|
||||||
|
ij_php_while_on_new_line = false
|
||||||
|
|
||||||
|
[{*.har,*.jsb2,*.jsb3,*.json,*.jsonc,*.postman_collection,*.postman_collection.json,*.postman_environment,*.postman_environment.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,.ws-context,composer.lock,jest.config}]
|
||||||
|
indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_json_array_wrapping = split_into_lines
|
||||||
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
|
ij_json_keep_line_breaks = true
|
||||||
|
ij_json_keep_trailing_comma = false
|
||||||
|
ij_json_object_wrapping = split_into_lines
|
||||||
|
ij_json_property_alignment = do_not_align
|
||||||
|
ij_json_space_after_colon = true
|
||||||
|
ij_json_space_after_comma = true
|
||||||
|
ij_json_space_before_colon = false
|
||||||
|
ij_json_space_before_comma = false
|
||||||
|
ij_json_spaces_within_braces = false
|
||||||
|
ij_json_spaces_within_brackets = false
|
||||||
|
ij_json_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
ij_continuation_indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||||
|
ij_html_align_attributes = true
|
||||||
|
ij_html_align_text = false
|
||||||
|
ij_html_attribute_wrap = on_every_item
|
||||||
|
ij_html_block_comment_add_space = false
|
||||||
|
ij_html_block_comment_at_first_column = true
|
||||||
|
ij_html_do_not_align_children_of_min_lines = 0
|
||||||
|
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6
|
||||||
|
ij_html_do_not_indent_children_of_tags = thead,tbody,tfoot
|
||||||
|
ij_html_enforce_quotes = true
|
||||||
|
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,strike,strong,sub,sup,textarea,tt,u,var
|
||||||
|
ij_html_keep_blank_lines = 2
|
||||||
|
ij_html_keep_indents_on_empty_lines = false
|
||||||
|
ij_html_keep_line_breaks = true
|
||||||
|
ij_html_keep_line_breaks_in_text = true
|
||||||
|
ij_html_keep_whitespaces = false
|
||||||
|
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||||
|
ij_html_line_comment_at_first_column = true
|
||||||
|
ij_html_new_line_after_last_attribute = when_multiline
|
||||||
|
ij_html_new_line_before_first_attribute = when_multiline
|
||||||
|
ij_html_quote_style = double
|
||||||
|
ij_html_remove_new_line_before_tags = br
|
||||||
|
ij_html_space_after_tag_name = false
|
||||||
|
ij_html_space_around_equality_in_attribute = false
|
||||||
|
ij_html_space_inside_empty_tag = true
|
||||||
|
ij_html_self_closing_tag = true
|
||||||
|
ij_html_text_wrap = normal
|
||||||
|
|
||||||
|
[{*.http,*.rest}]
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_http-request_call_parameters_wrap = normal
|
||||||
|
ij_http-request_method_parameters_wrap = split_into_lines
|
||||||
|
ij_http-request_space_before_comma = true
|
||||||
|
ij_http-request_spaces_around_assignment_operators = true
|
||||||
|
|
||||||
|
[{*.markdown,*.md}]
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_format_tables = true
|
||||||
|
ij_markdown_insert_quote_arrows_on_wrap = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_wrap_text_if_long = true
|
||||||
|
ij_markdown_wrap_text_inside_blockquotes = true
|
||||||
|
|
||||||
|
[{*.mk,GNUmakefile,GNUmakefile.inc,makefile,makefile.inc}]
|
||||||
|
ij_visual_guides =
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
indent_size = 2
|
||||||
|
ij_visual_guides =
|
||||||
|
ij_yaml_align_values_properties = do_not_align
|
||||||
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
ij_yaml_indent_sequence_value = true
|
||||||
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
|
ij_yaml_keep_line_breaks = true
|
||||||
|
ij_yaml_line_comment_add_space = false
|
||||||
|
ij_yaml_line_comment_add_space_on_reformat = false
|
||||||
|
ij_yaml_line_comment_at_first_column = true
|
||||||
|
ij_yaml_sequence_on_new_line = false
|
||||||
|
ij_yaml_space_before_colon = false
|
||||||
|
ij_yaml_spaces_within_braces = true
|
||||||
|
ij_yaml_spaces_within_brackets = true
|
||||||
53
.env.dist
Normal file
53
.env.dist
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# This file is a "template" of which env vars need to be defined for your application
|
||||||
|
# Copy this file to .env file for development, create environment variables when deploying to production
|
||||||
|
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_SECRET=changethis
|
||||||
|
APP_NAME=mineseeker
|
||||||
|
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
|
||||||
|
#TRUSTED_HOSTS=localhost,example.com
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Docker PostgreSQL is exposed on port 15432 — use that for bare-metal dev.
|
||||||
|
# Replace POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB with the values from your .env.
|
||||||
|
DATABASE_URL=postgresql://POSTGRES_USER:POSTGRES_PASSWORD@127.0.0.1:15432/POSTGRES_DB?serverVersion=18&charset=utf8
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
###> google/recaptcha ###
|
||||||
|
RECAPTCHA_SITE_KEY=changethis
|
||||||
|
RECAPTCHA_SECRET_KEY=changethis
|
||||||
|
###< google/recaptcha ###
|
||||||
|
|
||||||
|
###> minio/minio ###
|
||||||
|
MINIO_ROOT_USER=changethis
|
||||||
|
MINIO_ROOT_PASSWORD=changethis
|
||||||
|
MINIO_ENDPOINT=http://localhost:9000
|
||||||
|
MINIO_PUBLIC_URL=https://your-minio-subdomain.example.com
|
||||||
|
###< minio/minio ###
|
||||||
|
|
||||||
|
###> symfony/mailer ###
|
||||||
|
MAILER_DSN=smtp://localhost:1025
|
||||||
|
MAIL_DOMAIN=localhost
|
||||||
|
###< symfony/mailer ###
|
||||||
|
|
||||||
|
###> symfony/mercure-bundle ###
|
||||||
|
# See https://symfony.com/doc/current/mercure.html#configuration
|
||||||
|
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
|
||||||
|
MERCURE_URL=https://mine.local/.well-known/mercure
|
||||||
|
# The public URL of the Mercure hub, used by the browser to connect
|
||||||
|
MERCURE_PUBLIC_URL=https://mine.local/.well-known/mercure
|
||||||
|
# The secret used to sign the JWTs
|
||||||
|
MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
|
||||||
|
# Publisher JWT (must match publisher_jwt in your Caddyfile)
|
||||||
|
MERCURE_JWT_TOKEN=changethis
|
||||||
|
# Subscriber JWT sent to the browser so it can authenticate its EventSource connection
|
||||||
|
MERCURE_SUBSCRIBER_JWT=changethis
|
||||||
|
###< symfony/mercure-bundle ###
|
||||||
|
|
||||||
|
###> web-auth/webauthn-framework ###
|
||||||
|
WEBAUTHN_RP_ID=mine.local
|
||||||
|
WEBAUTHN_ORIGIN=https://mine.local
|
||||||
|
###< web-auth/webauthn-framework ###
|
||||||
39
.gitea/workflows/deploy.yml
Normal file
39
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: Deploy to Production
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: splendid-bear
|
||||||
|
steps:
|
||||||
|
- name: Checkout tag
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ gitea.token }}
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
export HOME=/tmp
|
||||||
|
git config --global credential.helper '!f() { echo "username=oauth2"; echo "password=$GITEA_TOKEN"; }; f'
|
||||||
|
git config --global --add safe.directory "${{ vars.PROD_APP_DIR }}"
|
||||||
|
cd "${{ vars.PROD_APP_DIR }}"
|
||||||
|
git remote set-url origin "${{ gitea.server_url }}/${{ gitea.repository }}.git"
|
||||||
|
git fetch --tags --force
|
||||||
|
git checkout "${{ gitea.ref_name }}"
|
||||||
|
|
||||||
|
- name: Write .env
|
||||||
|
env:
|
||||||
|
PROD_ENV_FILE: ${{ secrets.PROD_ENV_FILE }}
|
||||||
|
run: |
|
||||||
|
printf '%s' "$PROD_ENV_FILE" > "${{ vars.PROD_APP_DIR }}/.env"
|
||||||
|
|
||||||
|
- name: Build image
|
||||||
|
run: |
|
||||||
|
cd "${{ vars.PROD_APP_DIR }}"
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
- name: Start services
|
||||||
|
run: |
|
||||||
|
cd "${{ vars.PROD_APP_DIR }}"
|
||||||
|
docker compose up -d
|
||||||
55
.gitignore
vendored
55
.gitignore
vendored
@@ -1,41 +1,16 @@
|
|||||||
/app/config/parameters.yml
|
###> system7 - jotunheimr ###
|
||||||
/build/
|
compose.override.yaml
|
||||||
/phpunit.xml
|
+bak/
|
||||||
/var/*
|
.idea/
|
||||||
!/var/cache
|
node_modules/
|
||||||
/var/cache/*
|
|
||||||
!var/cache/.gitkeep
|
|
||||||
!/var/logs
|
|
||||||
/var/logs/*
|
|
||||||
!var/logs/.gitkeep
|
|
||||||
!/var/sessions
|
|
||||||
/var/sessions/*
|
|
||||||
!var/sessions/.gitkeep
|
|
||||||
!var/SymfonyRequirements.php
|
|
||||||
/vendor/
|
|
||||||
/web/bundles/
|
|
||||||
|
|
||||||
# s7 mods
|
|
||||||
/!/
|
|
||||||
/.idea/
|
|
||||||
/.idea/*
|
|
||||||
/.idea/workspace.xml
|
|
||||||
/.idea/dataSources.ids
|
|
||||||
/.idea/dataSources.xml
|
|
||||||
/.idea/dataSources.local.xml
|
|
||||||
|
|
||||||
web/css/*
|
|
||||||
web/js/*
|
|
||||||
web/uploads/*
|
|
||||||
|
|
||||||
phpunit.phar
|
|
||||||
phpunit-report/*
|
|
||||||
/node_modules/
|
|
||||||
/src/Mine/SeekerBundle/Resources/public/js/node/
|
|
||||||
/src/Mine/SeekerBundle/Resources/public/js/src/
|
|
||||||
|
|
||||||
nohup.out
|
nohup.out
|
||||||
src/Mine/SeekerBundle/Resources/public/js/index.js
|
/public/build/
|
||||||
src/Mine/SeekerBundle/Resources/public/js/index.min.js
|
/config/reference.php
|
||||||
/src/Mine/SeekerBundle/Resources/public/js/index.js.map
|
###< system7 - jotunheimr ###
|
||||||
npm-debug.log
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|||||||
72
CHANGELOG.md
72
CHANGELOG.md
@@ -2,6 +2,78 @@ Changelog
|
|||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
v2026.01 (2026-04-14)
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
New
|
||||||
|
~~~
|
||||||
|
- Registered users have avatars next to the timer #4. [Lang]
|
||||||
|
- Add opportunity to use profile picture. #4. [Lang]
|
||||||
|
- Add more stats and a dialog for the recent battle that can be
|
||||||
|
shareable #4. [Lang]
|
||||||
|
- Implement the 2FA authentication (TOTP and backup codes) #4. [Lang]
|
||||||
|
- Add beta logo to the corner #3. [Lang]
|
||||||
|
- Add mineseeker game to the symfony 4 project #3. [Lang]
|
||||||
|
- Upgrade to the latest symfony v4 #3. [Lang]
|
||||||
|
|
||||||
|
Changes
|
||||||
|
~~~~~~~
|
||||||
|
- Fix missing favicon #4. [Lang]
|
||||||
|
- Add modern Webauthn authentication #4. [Lang]
|
||||||
|
- Refactor all forms to have Symfony Form Types & Validation
|
||||||
|
Constrainsts - & implement Google ReCapthca v3 #4. [Lang]
|
||||||
|
- Add forgot password functionality #4. [Lang]
|
||||||
|
- Increase the minimum PHP version to the latest major - and massive
|
||||||
|
refactor on back-end, like Controllers and Repositories #4. [Lang]
|
||||||
|
- Redesign the resign dialog #4. [Lang]
|
||||||
|
- Re-implement the waiting for opponent dialog - refactor its gfx - &
|
||||||
|
add online user selection dialog #4. [Lang]
|
||||||
|
- Improve the gfx on homepage - implement login/register and activation
|
||||||
|
for authentication - and add the first version of profile page #4.
|
||||||
|
[Lang]
|
||||||
|
- Refactor and redesign the gfx on front-end #4. [Lang]
|
||||||
|
- Add timers to each player - renew the whole migration #4. [Lang]
|
||||||
|
- Use namespaces for front-end #4. [Lang]
|
||||||
|
- Replace webpack w/ vite & remove old, legacy jQuery from the code #4.
|
||||||
|
[Lang]
|
||||||
|
- More, massive refactor for front-end #4. [Lang]
|
||||||
|
- Massive refactor on front-end - and remove unnecessary deps #4. [Lang]
|
||||||
|
- Change the code style to fit the current standard #4. [Lang]
|
||||||
|
- Refactor to use Attributes instead of yaml markdown #4. [Lang]
|
||||||
|
- Outsource the Grid generation and interactions to the backend #4.
|
||||||
|
[Lang]
|
||||||
|
- Remove unnecessary variables and prune the Facebook registration
|
||||||
|
method #4. [Lang]
|
||||||
|
- Replace the legacy gos/web-socket-bundle & replace it with Mercure
|
||||||
|
protocol #4. [Lang]
|
||||||
|
- Created the first working solution since 7 yrs #4. [Lang]
|
||||||
|
- Make the first working version - the stepping is broken due to the
|
||||||
|
algorythm structure #4. [Lang]
|
||||||
|
- Change the composer default php minimum environment #3. [Lang]
|
||||||
|
- Change the default url to wss on frontend #3. [Lang]
|
||||||
|
- Refactor Rpc and Topic classes #3. [Lang]
|
||||||
|
- Refactor classes and reformat some layout #3. [Lang]
|
||||||
|
- Remove deprecated files #3. [Lang]
|
||||||
|
- Doc in README.md #3. [Lang]
|
||||||
|
- Gitignore a js.map file #2. [Lang]
|
||||||
|
|
||||||
|
Other
|
||||||
|
~~~~~
|
||||||
|
- Hg: pkg: new version release !skipChangelog. [Lang]
|
||||||
|
- Pkg: usr: solve the not-working mailing on dev env under docker #4.
|
||||||
|
[Lang]
|
||||||
|
- Deploy version 1.1.0 !deploy #11. [Lang]
|
||||||
|
|
||||||
|
|
||||||
|
1.1.0 (2019-10-26)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Changes
|
||||||
|
~~~~~~~
|
||||||
|
- Reinit project - disable redis module and make the project compatible
|
||||||
|
w/ PHP7.3 #2. [Lang]
|
||||||
|
|
||||||
|
|
||||||
0.4.0 (2019-10-26)
|
0.4.0 (2019-10-26)
|
||||||
------------------
|
------------------
|
||||||
- Change session driver to REDIS. [Lang]
|
- Change session driver to REDIS. [Lang]
|
||||||
|
|||||||
25
Caddyfile
Normal file
25
Caddyfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
{$CADDY_GLOBAL_OPTIONS}
|
||||||
|
|
||||||
|
frankenphp {
|
||||||
|
{$FRANKENPHP_CONFIG}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{$SERVER_NAME:localhost} {
|
||||||
|
log
|
||||||
|
|
||||||
|
root * /app/public
|
||||||
|
|
||||||
|
encode zstd br gzip
|
||||||
|
|
||||||
|
mercure {
|
||||||
|
transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
|
||||||
|
publisher_jwt {$MERCURE_JWT_SECRET} HS256
|
||||||
|
subscriber_jwt {$MERCURE_JWT_SECRET} HS256
|
||||||
|
anonymous
|
||||||
|
subscriptions
|
||||||
|
}
|
||||||
|
|
||||||
|
php_server
|
||||||
|
}
|
||||||
52
Dockerfile
Normal file
52
Dockerfile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
FROM oven/bun:1-alpine AS assets
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json bun.lock ./
|
||||||
|
RUN bun install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY vite.config.js ./
|
||||||
|
COPY assets/ assets/
|
||||||
|
COPY public/ public/
|
||||||
|
|
||||||
|
RUN bun run build
|
||||||
|
|
||||||
|
FROM dunglas/frankenphp:latest
|
||||||
|
|
||||||
|
RUN install-php-extensions \
|
||||||
|
pdo_pgsql \
|
||||||
|
gd \
|
||||||
|
intl \
|
||||||
|
zip \
|
||||||
|
opcache \
|
||||||
|
apcu \
|
||||||
|
sodium
|
||||||
|
|
||||||
|
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||||
|
RUN printf '[opcache]\nopcache.enable=1\nopcache.memory_consumption=256\nopcache.max_accelerated_files=20000\nopcache.validate_timestamps=0\n' \
|
||||||
|
> "$PHP_INI_DIR/conf.d/opcache.ini"
|
||||||
|
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
ENV APP_ENV=prod
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN composer install \
|
||||||
|
--no-dev \
|
||||||
|
--no-interaction \
|
||||||
|
--no-scripts \
|
||||||
|
--optimize-autoloader
|
||||||
|
|
||||||
|
COPY --from=assets /app/public/build ./public/build
|
||||||
|
|
||||||
|
RUN mkdir -p var/cache var/log var/sessions && \
|
||||||
|
chown -R www-data:www-data var/
|
||||||
|
|
||||||
|
COPY Caddyfile /etc/caddy/Caddyfile
|
||||||
|
COPY docker/entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
53
Makefile
Normal file
53
Makefile
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
.PHONY: help start start-build stop build down ps logs prune-everything db-reset mercure-jwt
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Available commands:"
|
||||||
|
@echo " make start - Start services without building (uses existing images)"
|
||||||
|
@echo " make start-build - Start services and build images if needed"
|
||||||
|
@echo " make stop - Stop running services"
|
||||||
|
@echo " make build - Build Docker images only"
|
||||||
|
@echo " make down - Stop and remove containers/networks"
|
||||||
|
@echo " make prune-everything - Prune volumes, networks and images (DANGEROUS!)"
|
||||||
|
@echo " make db-reset - Reset the database (drop, create, migrate) (DANGEROUS!)"
|
||||||
|
|
||||||
|
start:
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
start-build:
|
||||||
|
composer i
|
||||||
|
bun run build
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
stop:
|
||||||
|
docker compose stop
|
||||||
|
|
||||||
|
build:
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
down:
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
prune-everything:
|
||||||
|
@echo "WARNING: This will remove ALL containers, volumes, networks and images!"
|
||||||
|
@read -p "Type 'yes' to confirm: " confirm; \
|
||||||
|
if [ "$$confirm" != "yes" ]; then \
|
||||||
|
echo "Aborted."; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
docker compose down -v --rmi all --remove-orphans
|
||||||
|
|
||||||
|
mercure-jwt:
|
||||||
|
@php bin/generate-mercure-jwt.php
|
||||||
|
|
||||||
|
db-reset:
|
||||||
|
@echo "WARNING: This will DROP and RECREATE the database!"
|
||||||
|
@read -p "Type 'yes' to confirm: " confirm; \
|
||||||
|
if [ "$$confirm" != "yes" ]; then \
|
||||||
|
echo "Aborted."; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
bin/console doctrine:database:drop --force --if-exists --no-interaction
|
||||||
|
bin/console doctrine:database:create --if-not-exists --no-interaction
|
||||||
|
bin/console doctrine:migrations:migrate --no-interaction
|
||||||
292
README.md
292
README.md
@@ -1,42 +1,288 @@
|
|||||||
mineseeker
|
# MineSeeker
|
||||||
=========
|
|
||||||
|
|
||||||
A Symfony project created on September 22, 2016, 13:56 pm.
|
A real-time **1v1 multiplayer minesweeper** game played in the browser.
|
||||||
|
Two players race on the same hidden minefield — uncover safe cells to score points, but hit a mine and you hand the advantage to your opponent.
|
||||||
|
Games are live and synchronised instantly via a Mercure hub; no page reloads, no polling.
|
||||||
|
|
||||||
PROJECT VERSION 1.1.0-20191026
|
Created by [SplendidBear](https://www.splendidbear.org).
|
||||||
|
|
||||||
This is a Symfony 3 project w/ React JS in standalone mode and w/ WebSocket.
|
---
|
||||||
|
|
||||||
0.) Must installed modules w/ npm are in package.json + to global:
|
## Features
|
||||||
|
|
||||||
$ npm install webpack -g
|
- **Real-time 1v1 gameplay** — moves broadcast instantly over Mercure (server-sent events)
|
||||||
|
- **Guest & registered play** — jump in anonymously or create an account for stats and history
|
||||||
|
- **Full authentication stack** — email/password, passkeys (WebAuthn), TOTP 2FA with backup codes
|
||||||
|
- **Player profiles** — win/loss/draw stats, per-month charts, recent battle history with shareable replay links
|
||||||
|
- **Profile pictures** — uploaded to MinIO object storage, thumbnails generated on-the-fly by LiipImagine
|
||||||
|
- **Battle replay sharing** — share a direct link to any finished game
|
||||||
|
- **Docker-ready** — single `make start-build` brings up the full production-like stack
|
||||||
|
|
||||||
You will need a
|
---
|
||||||
.babelrc file w/ the presets
|
|
||||||
webpack.config.js - https://webpack.github.io/docs/webpack-for-browserify-users.html
|
|
||||||
same as dir where the package.json!!
|
|
||||||
|
|
||||||
(!) Tutorial: https://egghead.io/lessons/react-introduction-to-properties
|
## Tech stack
|
||||||
|
|
||||||
|
| Layer | Technology |
|
||||||
|
|---|---|
|
||||||
|
| Backend | PHP 8.5, Symfony 7.4, Doctrine ORM |
|
||||||
|
| Frontend | React 19, Vite, MUI, SCSS |
|
||||||
|
| Database | PostgreSQL 18 |
|
||||||
|
| Real-time | Mercure (built into FrankenPHP / Caddy) |
|
||||||
|
| File storage | MinIO (S3-compatible) |
|
||||||
|
| Image processing | LiipImagine + Flysystem |
|
||||||
|
| Server | FrankenPHP (Caddy + PHP in one binary) |
|
||||||
|
| Auth | Symfony Security, Scheb 2FA, web-auth/webauthn-framework |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
1.) Backend WebSocket server start as daemon - GeniusesOfSymfony/WebSocketBundle
|
## Requirements
|
||||||
|
|
||||||
$ nohup bin/console gos:websocket:server &
|
### Bare-metal development
|
||||||
|
- PHP >= 8.5 with extensions: `pdo_pgsql`, `gd`, `intl`, `zip`, `sodium`
|
||||||
|
- Composer 2
|
||||||
|
- Node.js 22 + Bun
|
||||||
|
- PostgreSQL 18
|
||||||
|
- Caddy with FrankenPHP and the Mercure module
|
||||||
|
- MailHog (or any SMTP server on port 1025)
|
||||||
|
- MinIO (listening on port 9000)
|
||||||
|
|
||||||
2.) React JS WebPack watch generator w/ babel presets: es2015, react
|
### Docker
|
||||||
|
- Docker Engine 24+
|
||||||
|
- Docker Compose v2
|
||||||
|
- Bun (for building frontend assets before `make start-build`)
|
||||||
|
- Composer (for `make start-build`)
|
||||||
|
|
||||||
$ webpack -p --config=webpack-prod.config.js
|
---
|
||||||
|
|
||||||
PROD
|
## Installation
|
||||||
|
|
||||||
$ webpack --progress --colors --watch -d
|
### 1. Clone the repository
|
||||||
|
|
||||||
DEV
|
```bash
|
||||||
|
git clone https://github.com/splendidbear/mineseeker.git
|
||||||
|
cd mineseeker
|
||||||
|
```
|
||||||
|
|
||||||
-d --> Debugger; If you write this line somewhere: debugger;
|
### 2. Configure environment
|
||||||
The browser will stop the code here!!!
|
|
||||||
|
|
||||||
3.) Connect to Prod
|
```bash
|
||||||
|
cp .env.dist .env
|
||||||
|
```
|
||||||
|
|
||||||
ssh xxsvci@laszlolang.com -i ~/.ssh/id_rsa_laszlolang
|
Edit `.env` and fill in every value. Key ones:
|
||||||
|
|
||||||
|
| Variable | What to set |
|
||||||
|
|---|---|
|
||||||
|
| `APP_SECRET` | Random 32-byte hex: `openssl rand -hex 32` |
|
||||||
|
| `POSTGRES_USER/PASSWORD/DB` | Your PostgreSQL credentials |
|
||||||
|
| `MINIO_ROOT_USER/PASSWORD` | MinIO admin credentials |
|
||||||
|
| `MINIO_ENDPOINT` | `http://localhost:9000` (bare-metal) |
|
||||||
|
| `MINIO_PUBLIC_URL` | Public URL browsers use to reach MinIO |
|
||||||
|
| `RECAPTCHA_SITE_KEY/SECRET_KEY` | Google reCAPTCHA v3 keys for your domain |
|
||||||
|
| `MERCURE_JWT_SECRET` | Random secret (generated in step 3) |
|
||||||
|
| `MERCURE_JWT_TOKEN` | Signed publisher JWT (generated in step 3) |
|
||||||
|
| `MERCURE_SUBSCRIBER_JWT` | Signed subscriber JWT (generated in step 3) |
|
||||||
|
| `MAILER_DSN` | `smtp://localhost:1025` for MailHog in dev |
|
||||||
|
|
||||||
|
### 3. Generate Mercure JWT tokens
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer install
|
||||||
|
make mercure-jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the printed values into `.env` and into the `publisher_jwt` / `subscriber_jwt` lines of your Caddy Mercure block, then reload Caddy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl reload caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4a. Run with Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make start-build
|
||||||
|
```
|
||||||
|
|
||||||
|
This installs PHP dependencies, builds the frontend assets with Bun, builds the Docker image, and starts all services (`app`, `db`, `mail`, `minio`, `minio_init`).
|
||||||
|
|
||||||
|
The app is available at `http://localhost:10080` (or the domain set in `APP_PUBLIC_HOSTNAME`).
|
||||||
|
|
||||||
|
To apply any code changes later, run the same command again.
|
||||||
|
|
||||||
|
### 4b. Run bare-metal (development)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer install
|
||||||
|
bun install
|
||||||
|
bun run dev # Vite dev server with hot-reload
|
||||||
|
php bin/console doctrine:migrations:migrate --no-interaction
|
||||||
|
```
|
||||||
|
|
||||||
|
Start MinIO and MailHog, then open the URL configured in your Caddy vhost.
|
||||||
|
|
||||||
|
### 5. MinIO bucket setup
|
||||||
|
|
||||||
|
**Docker** — handled automatically on first start by the `minio_init` service. No action needed.
|
||||||
|
|
||||||
|
**Bare-metal** — run once after MinIO is up:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mc alias set local http://localhost:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
|
||||||
|
mc mb local/mineseeker
|
||||||
|
echo '' | mc pipe local/mineseeker/media/.keep
|
||||||
|
echo '' | mc pipe local/mineseeker/cache/.keep
|
||||||
|
# Apply public-read policy for media/ and cache/ — see docker/minio-init.sh for the JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development environment
|
||||||
|
|
||||||
|
When running the Docker stack locally you typically want to catch outgoing emails instead of relaying them through a real SMTP server.
|
||||||
|
The production `compose.yaml` uses Postfix for actual mail delivery and must not be edited for local overrides.
|
||||||
|
Use a `compose.override.yaml` file instead — Docker Compose merges it automatically on top of the base file whenever both are present.
|
||||||
|
|
||||||
|
### Email: replace Postfix with MailHog
|
||||||
|
|
||||||
|
Create `compose.override.yaml` in the project root (it is git-ignored and never reaches production):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
environment:
|
||||||
|
MAILER_DSN: smtp://mail:1025?verify_peer=0
|
||||||
|
mail:
|
||||||
|
image: mailhog/mailhog:latest
|
||||||
|
ports:
|
||||||
|
- "1025:1025"
|
||||||
|
- "8025:8025"
|
||||||
|
```
|
||||||
|
|
||||||
|
This replaces the `mail` service image with MailHog and points the application's mailer at its SMTP port (`1025`).
|
||||||
|
No other files need to change.
|
||||||
|
|
||||||
|
After adding the file, restart the stack:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make start-build
|
||||||
|
```
|
||||||
|
|
||||||
|
All emails sent by the application are now captured by MailHog.
|
||||||
|
Open the web UI at **http://localhost:8025** to inspect them.
|
||||||
|
|
||||||
|
> **Production note** — `compose.override.yaml` is listed in `.gitignore`.
|
||||||
|
> Never commit it; the production server must only see `compose.yaml` with Postfix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploying to production
|
||||||
|
|
||||||
|
Releases are automated via Gitea Actions. Pushing a tag that starts with `v` (e.g. `v2026.01`) triggers the workflow at `.gitea/workflows/deploy.yml`.
|
||||||
|
The job runs on a **self-hosted runner** installed on the production server — the server only needs an outbound connection to Gitea, no open SSH port required.
|
||||||
|
The `app` image is rebuilt with the new code; the database and storage containers are untouched so all data is preserved.
|
||||||
|
|
||||||
|
### Gitea repository variables and secrets
|
||||||
|
|
||||||
|
**Variable** (plaintext, editable — **Repository → Settings → Variables**):
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|---|---|
|
||||||
|
| `PROD_APP_DIR` | Absolute path on the server (e.g. `/var/www/mineseeker`) |
|
||||||
|
|
||||||
|
**Secret** (encrypted, write-only — **Repository → Settings → Secrets**):
|
||||||
|
|
||||||
|
| Secret | Value |
|
||||||
|
|---|---|
|
||||||
|
| `PROD_ENV_FILE` | Full content of the production `.env` file (see below) |
|
||||||
|
|
||||||
|
The workflow writes `PROD_ENV_FILE` to `.env` on every deploy, so you never need to manage the file on the server manually. To update a credential, overwrite the secret in Gitea and push a new tag.
|
||||||
|
|
||||||
|
#### `PROD_ENV_FILE` contents
|
||||||
|
|
||||||
|
Paste the filled-in `.env` file as the secret value:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
APP_NAME=mineseeker
|
||||||
|
APP_ENV=prod
|
||||||
|
APP_SECRET="<openssl rand -hex 32>"
|
||||||
|
|
||||||
|
DATABASE_URL=postgresql://POSTGRES_USER:POSTGRES_PASSWORD@db:5432/POSTGRES_DB?serverVersion=18&charset=utf8
|
||||||
|
|
||||||
|
POSTGRES_USER=mineseeker
|
||||||
|
POSTGRES_PASSWORD="<strong password>"
|
||||||
|
POSTGRES_DB=mineseeker
|
||||||
|
POSTGRES_VERSION=18
|
||||||
|
|
||||||
|
MINIO_ROOT_USER=mineseeker
|
||||||
|
MINIO_ROOT_PASSWORD="<strong password>"
|
||||||
|
MINIO_ENDPOINT=http://minio:9000
|
||||||
|
MINIO_PUBLIC_URL=https://aws.mineseeker.hu
|
||||||
|
|
||||||
|
MAILER_DSN=smtp://mail:25?verify_peer=0
|
||||||
|
MAIL_DOMAIN=mineseeker.hu
|
||||||
|
|
||||||
|
RECAPTCHA_SITE_KEY="<your reCAPTCHA v3 site key>"
|
||||||
|
RECAPTCHA_SECRET_KEY="<your reCAPTCHA v3 secret key>"
|
||||||
|
|
||||||
|
MERCURE_URL=https://mineseeker.hu/.well-known/mercure
|
||||||
|
MERCURE_PUBLIC_URL=https://mineseeker.hu/.well-known/mercure
|
||||||
|
MERCURE_JWT_SECRET="<generated by make mercure-jwt>"
|
||||||
|
MERCURE_JWT_TOKEN="<generated by make mercure-jwt>"
|
||||||
|
MERCURE_SUBSCRIBER_JWT="<generated by make mercure-jwt>"
|
||||||
|
|
||||||
|
APP_PUBLIC_HOSTNAME=mineseeker.hu
|
||||||
|
WEBAUTHN_RP_ID=mineseeker.hu
|
||||||
|
WEBAUTHN_ORIGIN=https://mineseeker.hu
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production server: one-time setup
|
||||||
|
|
||||||
|
The server needs Docker, Git, and a self-hosted `act_runner` registered against the Gitea repository. Bun and Composer run inside the multi-stage Dockerfile, so they are not needed on the server.
|
||||||
|
|
||||||
|
#### 1. Clone the repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.mineseeker.hu/youruser/mineseeker.git /var/www/mineseeker
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Generate Mercure JWT tokens (run once locally)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer install # only needed for this step
|
||||||
|
make mercure-jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the three printed values into the `PROD_ENV_FILE` secret.
|
||||||
|
|
||||||
|
#### 5. First deploy
|
||||||
|
|
||||||
|
Trigger it by pushing the first tag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v2026.01
|
||||||
|
git push origin v2026.01
|
||||||
|
```
|
||||||
|
|
||||||
|
This writes `.env`, builds the Docker image, starts all services, runs migrations, and initialises the MinIO buckets automatically via `minio_init`.
|
||||||
|
|
||||||
|
#### 6. Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps # all services should be healthy/running
|
||||||
|
docker compose logs app # look for "Starting FrankenPHP"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Releasing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v2026.01
|
||||||
|
git push origin v2026.01
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
LGPL-3.0 — see [LICENSE](LICENSE) for details.
|
||||||
|
|
||||||
|
© 2026 [SplendidBear](https://www.splendidbear.org)
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<IfModule mod_authz_core.c>
|
|
||||||
Require all denied
|
|
||||||
</IfModule>
|
|
||||||
<IfModule !mod_authz_core.c>
|
|
||||||
Order deny,allow
|
|
||||||
Deny from all
|
|
||||||
</IfModule>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
|
|
||||||
|
|
||||||
class AppCache extends HttpCache
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Symfony\Component\HttpKernel\Kernel;
|
|
||||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
|
||||||
|
|
||||||
class AppKernel extends Kernel
|
|
||||||
{
|
|
||||||
public function registerBundles()
|
|
||||||
{
|
|
||||||
$bundles = [
|
|
||||||
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
|
|
||||||
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
|
|
||||||
new Symfony\Bundle\TwigBundle\TwigBundle(),
|
|
||||||
new Symfony\Bundle\MonologBundle\MonologBundle(),
|
|
||||||
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
|
|
||||||
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
|
|
||||||
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
|
|
||||||
|
|
||||||
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
|
|
||||||
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
|
|
||||||
new FOS\UserBundle\FOSUserBundle(),
|
|
||||||
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
|
|
||||||
new Gos\Bundle\WebSocketBundle\GosWebSocketBundle(),
|
|
||||||
new Gos\Bundle\PubSubRouterBundle\GosPubSubRouterBundle(),
|
|
||||||
new Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle(),
|
|
||||||
new Snc\RedisBundle\SncRedisBundle(),
|
|
||||||
new CL\Bundle\SlackBundle\CLSlackBundle(),
|
|
||||||
|
|
||||||
new Jotunheimr\AdminBundle\JotunheimrAdminBundle(),
|
|
||||||
new Jotunheimr\UserBundle\JotunheimrUserBundle(),
|
|
||||||
new Mine\SeekerBundle\MineSeekerBundle(),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
|
||||||
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
|
|
||||||
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
|
|
||||||
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
|
|
||||||
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $bundles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRootDir()
|
|
||||||
{
|
|
||||||
return __DIR__;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCacheDir()
|
|
||||||
{
|
|
||||||
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLogDir()
|
|
||||||
{
|
|
||||||
return dirname(__DIR__).'/var/logs';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function registerContainerConfiguration(LoaderInterface $loader)
|
|
||||||
{
|
|
||||||
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="Cache-control" content="max-age=1209600;public">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="keywords" content="game,mineseeker,mine,seeker,laszlolang.com">
|
|
||||||
<meta name="robots" content="index,follow">
|
|
||||||
<meta name="revisit-after" content="2 days">
|
|
||||||
<meta name="resource-type" content="document">
|
|
||||||
<meta name="country" content="Hungary">
|
|
||||||
<meta name="description" content="This is a new minesweeper, multiplayer game.">
|
|
||||||
<meta name="content-language" content="hu,hun,hungarian">
|
|
||||||
{% include '@MineSeeker/Recent/favicon.html.twig' %}
|
|
||||||
<meta property="fb:app_id" content="{{ facebook_api }}">
|
|
||||||
{% block metas %}{% endblock %}
|
|
||||||
<title>MineSeeker{% block title %}{% endblock %}</title>
|
|
||||||
{% block stylesheets %}{% endblock %}
|
|
||||||
{% include '@MineSeeker/Recent/google-analytics.html.twig' %}
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="fb-root"></div>
|
|
||||||
|
|
||||||
{% block bodyTop %}{% endblock %}
|
|
||||||
|
|
||||||
<header>
|
|
||||||
{% block header %}{% endblock %}
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
{% block body %}{% endblock %}
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
{% block footer %}{% endblock %}
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
{% block javascripts %}
|
|
||||||
{% javascripts filter='?uglifyjs2'
|
|
||||||
'@JotunheimrAdminBundle/Resources/public/js/vendor/plugins/jQuery/jquery-3.0.0.min.js'
|
|
||||||
'@JotunheimrAdminBundle/Resources/public/js/vendor/plugins/jQuery/jquery-migrate-3.0.0.min.js'
|
|
||||||
'@JotunheimrAdminBundle/Resources/public/js/vendor/bootstrap/js/bootstrap.min.js' %}
|
|
||||||
<script type="text/javascript" src="{{ asset_url }}"></script>
|
|
||||||
{% endjavascripts %}
|
|
||||||
|
|
||||||
{% include '@MineSeeker/Recent/facebook.html.twig' %}
|
|
||||||
{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
|
||||||
use Composer\Autoload\ClassLoader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var ClassLoader $loader
|
|
||||||
*/
|
|
||||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
|
||||||
|
|
||||||
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
|
|
||||||
|
|
||||||
return $loader;
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
imports:
|
|
||||||
- { resource: security.yml }
|
|
||||||
- { resource: services.yml }
|
|
||||||
- { resource: "@JotunheimrAdminBundle/Resources/config/config.yml" }
|
|
||||||
- { resource: "@JotunheimrUserBundle/Resources/config/config.yml" }
|
|
||||||
- { resource: "@MineSeekerBundle/Resources/config/config.yml" }
|
|
||||||
- { resource: "@MineSeekerBundle/Resources/config/services.yml" }
|
|
||||||
|
|
||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
|
||||||
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
|
||||||
parameters:
|
|
||||||
locale: en
|
|
||||||
mailer_user: 7system7@gmail.com
|
|
||||||
mailer_name: Lang
|
|
||||||
|
|
||||||
framework:
|
|
||||||
#esi: ~
|
|
||||||
translator: { fallbacks: ["%locale%"] }
|
|
||||||
secret: "%secret%"
|
|
||||||
router:
|
|
||||||
resource: "%kernel.root_dir%/config/routing.yml"
|
|
||||||
strict_requirements: ~
|
|
||||||
form: ~
|
|
||||||
csrf_protection: ~
|
|
||||||
validation: { enable_annotations: true }
|
|
||||||
#serializer: { enable_annotations: true }
|
|
||||||
templating:
|
|
||||||
engines: ['twig']
|
|
||||||
default_locale: "%locale%"
|
|
||||||
trusted_hosts: ~
|
|
||||||
trusted_proxies: ~
|
|
||||||
session: ~
|
|
||||||
# http://symfony.com/doc/current/reference/configuration/framework.html#handler-id
|
|
||||||
# handler_id: session.handler.native_file
|
|
||||||
# save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
|
|
||||||
# handler_id: session.handler.pdo
|
|
||||||
fragments: ~
|
|
||||||
http_method_override: true
|
|
||||||
assets: ~
|
|
||||||
|
|
||||||
# Twig Configuration
|
|
||||||
twig:
|
|
||||||
debug: "%kernel.debug%"
|
|
||||||
strict_variables: "%kernel.debug%"
|
|
||||||
globals:
|
|
||||||
version: "0.37.18 (beta7)"
|
|
||||||
facebook_api: "%facebook.api%"
|
|
||||||
facebook_scope: "%facebook.scope%"
|
|
||||||
facebook_api_version: "%facebook.version%"
|
|
||||||
|
|
||||||
# Doctrine Configuration
|
|
||||||
doctrine:
|
|
||||||
dbal:
|
|
||||||
driver: pdo_mysql
|
|
||||||
host: "%database_host%"
|
|
||||||
port: "%database_port%"
|
|
||||||
dbname: "%database_name%"
|
|
||||||
user: "%database_user%"
|
|
||||||
password: "%database_password%"
|
|
||||||
charset: UTF8
|
|
||||||
# if using pdo_sqlite as your database driver:
|
|
||||||
# 1. add the path in parameters.yml
|
|
||||||
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
|
|
||||||
# 2. Uncomment database_path in parameters.yml.dist
|
|
||||||
# 3. Uncomment next line:
|
|
||||||
# path: "%database_path%"
|
|
||||||
|
|
||||||
orm:
|
|
||||||
auto_generate_proxy_classes: "%kernel.debug%"
|
|
||||||
naming_strategy: doctrine.orm.naming_strategy.underscore
|
|
||||||
auto_mapping: true
|
|
||||||
|
|
||||||
# Assetic Configuration
|
|
||||||
assetic:
|
|
||||||
debug: "%kernel.debug%"
|
|
||||||
use_controller: "%kernel.debug%"
|
|
||||||
bundles: ~
|
|
||||||
node: /usr/bin/nodejs
|
|
||||||
filters:
|
|
||||||
cssrewrite: ~
|
|
||||||
uglifyjs2:
|
|
||||||
bin: "%kernel.root_dir%/../node_modules/uglify-js/bin/uglifyjs"
|
|
||||||
no_copyright: true
|
|
||||||
uglifycss:
|
|
||||||
bin: "%kernel.root_dir%/../node_modules/uglifycss/uglifycss"
|
|
||||||
|
|
||||||
# FOS User Configuration
|
|
||||||
fos_user:
|
|
||||||
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
|
|
||||||
firewall_name: secured_area
|
|
||||||
user_class: Jotunheimr\UserBundle\Entity\User
|
|
||||||
from_email:
|
|
||||||
address: "%mailer_user%"
|
|
||||||
sender_name: "%mailer_name%"
|
|
||||||
|
|
||||||
# Facebook OAuth
|
|
||||||
hwi_oauth:
|
|
||||||
firewall_names: [secured_area]
|
|
||||||
resource_owners:
|
|
||||||
facebook:
|
|
||||||
type: facebook
|
|
||||||
client_id: "%facebook.api%"
|
|
||||||
client_secret: "%facebook.api-secret%"
|
|
||||||
scope: "%facebook.scope%"
|
|
||||||
options:
|
|
||||||
display: popup
|
|
||||||
auth_type: rerequest
|
|
||||||
csrf: true
|
|
||||||
|
|
||||||
# Slack integration
|
|
||||||
cl_slack:
|
|
||||||
api_token: xoxp-107639806167-107029084564-115427085733-cccaa4f96c89c87ce680c7f22acfd001
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
imports:
|
|
||||||
- { resource: parameters_dev.yml }
|
|
||||||
- { resource: config.yml }
|
|
||||||
|
|
||||||
framework:
|
|
||||||
router:
|
|
||||||
resource: "%kernel.root_dir%/config/routing_dev.yml"
|
|
||||||
strict_requirements: true
|
|
||||||
profiler: { only_exceptions: false }
|
|
||||||
|
|
||||||
web_profiler:
|
|
||||||
toolbar: true
|
|
||||||
intercept_redirects: false
|
|
||||||
|
|
||||||
|
|
||||||
# Swiftmailer Configuration
|
|
||||||
swiftmailer:
|
|
||||||
transport: "%mailer_transport%"
|
|
||||||
host: "%mailer_host%"
|
|
||||||
username: "%mailer_user%"
|
|
||||||
password: "%mailer_password%"
|
|
||||||
spool: { type: memory }
|
|
||||||
|
|
||||||
monolog:
|
|
||||||
handlers:
|
|
||||||
main:
|
|
||||||
type: stream
|
|
||||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
|
||||||
level: debug
|
|
||||||
channels: [!event]
|
|
||||||
console:
|
|
||||||
type: console
|
|
||||||
channels: [!event, !doctrine]
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
facebook.api: 320599508311862
|
|
||||||
facebook.api-secret: 18d4f48cdd274bccee2678e5eff3f557
|
|
||||||
facebook.version: 'v2.8'
|
|
||||||
facebook.scope: 'public_profile,email,user_friends'
|
|
||||||
mineseeker.websocket: 6450
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
imports:
|
|
||||||
- { resource: parameters_prod.yml }
|
|
||||||
- { resource: config.yml }
|
|
||||||
|
|
||||||
# Swiftmailer Configuration
|
|
||||||
swiftmailer:
|
|
||||||
transport: "%mailer_transport%"
|
|
||||||
host: "%mailer_host%"
|
|
||||||
username: "%mailer_user%"
|
|
||||||
password: "%mailer_password%"
|
|
||||||
spool: { type: memory }
|
|
||||||
|
|
||||||
monolog:
|
|
||||||
handlers:
|
|
||||||
main:
|
|
||||||
type: fingers_crossed
|
|
||||||
action_level: error
|
|
||||||
handler: nested
|
|
||||||
nested:
|
|
||||||
type: stream
|
|
||||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
|
||||||
level: debug
|
|
||||||
console:
|
|
||||||
type: console
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
facebook.api: 320597498312063
|
|
||||||
facebook.api-secret: c751bec8a3c5313ff2e5a83769bf1109
|
|
||||||
facebook.version: 'v2.8'
|
|
||||||
facebook.scope: 'public_profile,email,user_friends'
|
|
||||||
mineseeker.websocket: 8080
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
imports:
|
|
||||||
- { resource: config_dev.yml }
|
|
||||||
|
|
||||||
framework:
|
|
||||||
test: ~
|
|
||||||
session:
|
|
||||||
storage_id: session.storage.mock_file
|
|
||||||
profiler:
|
|
||||||
collect: false
|
|
||||||
|
|
||||||
web_profiler:
|
|
||||||
toolbar: false
|
|
||||||
intercept_redirects: false
|
|
||||||
|
|
||||||
swiftmailer:
|
|
||||||
disable_delivery: true
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# This file is a "template" of what your parameters.yml file should look like
|
|
||||||
# Set parameters here that may be different on each deployment target of the app, e.g. development, staging, production.
|
|
||||||
# http://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
|
||||||
parameters:
|
|
||||||
database_host: 127.0.0.1
|
|
||||||
database_port: ~
|
|
||||||
database_name: symfony
|
|
||||||
database_user: root
|
|
||||||
database_password: ~
|
|
||||||
# You should uncomment this if you want use pdo_sqlite
|
|
||||||
# database_path: "%kernel.root_dir%/data.db3"
|
|
||||||
|
|
||||||
mailer_transport: smtp
|
|
||||||
mailer_host: 127.0.0.1
|
|
||||||
mailer_user: ~
|
|
||||||
mailer_password: ~
|
|
||||||
|
|
||||||
# A secret key that's used to generate certain security-related tokens
|
|
||||||
secret: ThisTokenIsNotSoSecretChangeIt
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# This file is auto-generated during the composer install
|
|
||||||
parameters:
|
|
||||||
database_host: 127.0.0.1
|
|
||||||
database_port: null
|
|
||||||
database_name: mine
|
|
||||||
database_user: root
|
|
||||||
database_password: ~
|
|
||||||
mailer_transport: smtp
|
|
||||||
mailer_host: 127.0.0.1
|
|
||||||
mailer_user: null
|
|
||||||
mailer_password: null
|
|
||||||
secret: bbcd5df99fc340558fb3995c198a9b4764db72ba
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# This file is auto-generated during the composer install
|
|
||||||
parameters:
|
|
||||||
database_host: 127.0.0.1
|
|
||||||
database_port: null
|
|
||||||
database_name: mine
|
|
||||||
database_user: root
|
|
||||||
database_password: 'bazmeg'
|
|
||||||
mailer_transport: smtp
|
|
||||||
mailer_host: 127.0.0.1
|
|
||||||
mailer_user: null
|
|
||||||
mailer_password: null
|
|
||||||
secret: e25d036bb9c7ece0f2049984a1fa2f0cab295aaa
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
fos_user:
|
|
||||||
resource: "@FOSUserBundle/Resources/config/routing/all.xml"
|
|
||||||
|
|
||||||
JotunheimrUserBundle:
|
|
||||||
resource: "@JotunheimrUserBundle/Resources/config/routing.yml"
|
|
||||||
prefix: /
|
|
||||||
|
|
||||||
JotunheimrAdminBundle:
|
|
||||||
resource: "@JotunheimrAdminBundle/Resources/config/routing.yml"
|
|
||||||
prefix: /
|
|
||||||
|
|
||||||
MineSeekerBundle:
|
|
||||||
resource: "@MineSeekerBundle/Resources/config/routing.yml"
|
|
||||||
prefix: /
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
_wdt:
|
|
||||||
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
|
|
||||||
prefix: /_wdt
|
|
||||||
|
|
||||||
_profiler:
|
|
||||||
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
|
|
||||||
prefix: /_profiler
|
|
||||||
|
|
||||||
_errors:
|
|
||||||
resource: "@TwigBundle/Resources/config/routing/errors.xml"
|
|
||||||
prefix: /_error
|
|
||||||
|
|
||||||
_main:
|
|
||||||
resource: routing.yml
|
|
||||||
schemes: [http]
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
security:
|
|
||||||
encoders:
|
|
||||||
FOS\UserBundle\Model\UserInterface: bcrypt
|
|
||||||
|
|
||||||
role_hierarchy:
|
|
||||||
ROLE_ADMIN: ROLE_USER
|
|
||||||
ROLE_SUPER_ADMIN: ROLE_ADMIN
|
|
||||||
|
|
||||||
providers:
|
|
||||||
fos_userbundle:
|
|
||||||
id: fos_user.user_provider.username_email
|
|
||||||
|
|
||||||
firewalls:
|
|
||||||
secured_area:
|
|
||||||
anonymous: ~
|
|
||||||
oauth:
|
|
||||||
resource_owners:
|
|
||||||
facebook: /login/check-facebook
|
|
||||||
google: /login/check-google
|
|
||||||
my_github: /login/check-github
|
|
||||||
login_path: /login
|
|
||||||
failure_path: /login
|
|
||||||
use_forward: false
|
|
||||||
oauth_user_provider:
|
|
||||||
service: jotun.user_provider
|
|
||||||
remember_me:
|
|
||||||
secret: "%secret%"
|
|
||||||
lifetime: 604800
|
|
||||||
path: /
|
|
||||||
domain: ~
|
|
||||||
user_provider: fos_userbundle
|
|
||||||
form_login:
|
|
||||||
provider: fos_userbundle
|
|
||||||
csrf_token_generator: security.csrf.token_manager
|
|
||||||
default_target_path: /
|
|
||||||
remember_me: true
|
|
||||||
logout:
|
|
||||||
path: /logout
|
|
||||||
target: /
|
|
||||||
|
|
||||||
access_control:
|
|
||||||
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
|
||||||
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
|
||||||
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
|
||||||
- { path: ^/play, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
|
||||||
- { path: ^/admin, role: ROLE_SUPER_ADMIN }
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Learn more about services, parameters and containers at
|
|
||||||
# http://symfony.com/doc/current/book/service_container.html
|
|
||||||
parameters:
|
|
||||||
# parameter_name: value
|
|
||||||
|
|
||||||
services:
|
|
||||||
# service_name:
|
|
||||||
# class: AppBundle\Directory\ClassName
|
|
||||||
# arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
|
|
||||||
15
assets/css/_fontawesome-config.scss
Normal file
15
assets/css/_fontawesome-config.scss
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*!*
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$font-path: "/webfonts";
|
||||||
|
|
||||||
|
@import '@fortawesome/fontawesome-free/scss/fontawesome';
|
||||||
|
@import '@fortawesome/fontawesome-free/scss/brands';
|
||||||
|
@import '@fortawesome/fontawesome-free/scss/solid';
|
||||||
|
@import '@fortawesome/fontawesome-free/scss/regular';
|
||||||
12
assets/css/_fonts-config.scss
Normal file
12
assets/css/_fonts-config.scss
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*!*
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '@fontsource/rajdhani';
|
||||||
|
@import '@fontsource/changa-one';
|
||||||
|
@import '@fontsource/open-sans/700';
|
||||||
9
assets/css/homepage/_animations.scss
Normal file
9
assets/css/homepage/_animations.scss
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@keyframes appear {
|
||||||
|
from { opacity: 0; transform: scale(0.94); }
|
||||||
|
to { opacity: 1; transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rise {
|
||||||
|
from { opacity: 0; transform: translateY(16px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
111
assets/css/homepage/_auth-bar.scss
Normal file
111
assets/css/homepage/_auth-bar.scss
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
.hero-auth {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
right: 36px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-auth-user {
|
||||||
|
font: 600 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.75);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
i { font-size: 15px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-auth-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font: 600 12px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
background: rgba(255, 255, 255, 0.06);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 7px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
border-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--register {
|
||||||
|
color: rgba(149, 207, 245, 0.8);
|
||||||
|
border-color: rgba(35, 111, 135, 0.4);
|
||||||
|
background: rgba(35, 111, 135, 0.12);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(35, 111, 135, 0.28);
|
||||||
|
border-color: rgba(149, 207, 245, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--security {
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
border-color: rgba(35, 111, 135, 0.22);
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
background: rgba(35, 111, 135, 0.14);
|
||||||
|
border-color: rgba(35, 111, 135, 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--out {
|
||||||
|
background: transparent;
|
||||||
|
border-color: rgba(173, 10, 5, 0.3);
|
||||||
|
color: rgba(246, 125, 82, 0.7);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(173, 10, 5, 0.15);
|
||||||
|
border-color: rgba(246, 125, 82, 0.5);
|
||||||
|
color: #f67d52;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--profile {
|
||||||
|
color: rgba(149, 207, 245, 0.8);
|
||||||
|
border-color: rgba(35, 111, 135, 0.35);
|
||||||
|
background: rgba(35, 111, 135, 0.08);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(35, 111, 135, 0.22);
|
||||||
|
border-color: rgba(149, 207, 245, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-auth-avatar {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.5);
|
||||||
|
|
||||||
|
&--initials {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.45) 0%, rgba(173, 10, 5, 0.3) 100%);
|
||||||
|
font: 800 9px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
430
assets/css/homepage/_auth.scss
Normal file
430
assets/css/homepage/_auth.scss
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
.auth-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40px 20px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-flash {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 420px;
|
||||||
|
padding: 12px 18px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font: 600 14px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background: rgba(26, 104, 68, 0.25);
|
||||||
|
border: 1px solid rgba(42, 158, 96, 0.4);
|
||||||
|
color: #a0f0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background: rgba(173, 10, 5, 0.18);
|
||||||
|
border: 1px solid rgba(173, 10, 5, 0.4);
|
||||||
|
color: #f6a090;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Check your inbox" confirmation card
|
||||||
|
.auth-card--sent {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-sent-icon {
|
||||||
|
font-size: 52px;
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
filter: drop-shadow(0 0 16px rgba(35, 111, 135, 0.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-sent-email {
|
||||||
|
font: 700 16px 'Rajdhani', sans-serif;
|
||||||
|
color: #95cff5;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin: 0 0 20px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-sent-note {
|
||||||
|
font: 400 14px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
line-height: 1.7;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
strong { color: rgba(255, 255, 255, 0.75); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-card {
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.2);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 44px 48px 40px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 420px;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
box-shadow: 0 8px 48px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-title {
|
||||||
|
font: 800 30px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-sub {
|
||||||
|
font: 400 14px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-error {
|
||||||
|
background: rgba(173, 10, 5, 0.18);
|
||||||
|
border: 1px solid rgba(173, 10, 5, 0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
font: 600 13px 'Rajdhani', sans-serif;
|
||||||
|
color: #f6a090;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-label {
|
||||||
|
font: 700 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-input-wrap {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-input-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 11px;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
font-size: 13px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-input {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 11px 14px 11px 34px;
|
||||||
|
font: 500 15px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
transition: border-color 200ms ease, background 200ms ease;
|
||||||
|
|
||||||
|
&::placeholder { color: rgba(255, 255, 255, 0.2); }
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
background: rgba(35, 111, 135, 0.1);
|
||||||
|
border-color: rgba(149, 207, 245, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
border-color: rgba(173, 10, 5, 0.6) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-field-error {
|
||||||
|
font: 500 12px 'Rajdhani', sans-serif;
|
||||||
|
color: #f6a090;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-below-password {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-remember {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font: 500 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
margin-top: -4px;
|
||||||
|
|
||||||
|
input[type="checkbox"] { accent-color: #236f87; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-submit {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: linear-gradient(to bottom, #ad0a05 0%, #d4401a 55%, #f67d52 100%);
|
||||||
|
border: 1px solid rgba(246, 125, 82, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #ffffff;
|
||||||
|
font: 700 16px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 6px;
|
||||||
|
box-shadow: 0 4px 20px rgba(173, 10, 5, 0.35);
|
||||||
|
transition: all 220ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #c91008 0%, #e5521e 55%, #ff8c61 100%);
|
||||||
|
box-shadow: 0 6px 28px rgba(173, 10, 5, 0.6);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active { transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-cancel {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: linear-gradient(to bottom, #1a1a1a 0%, #2d2d2d 55%, #404040 100%);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #ffffff;
|
||||||
|
font: 700 16px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 6px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
|
||||||
|
transition: all 220ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #2d2d2d 0%, #3d3d3d 55%, #505050 100%);
|
||||||
|
box-shadow: 0 6px 28px rgba(0, 0, 0, 0.6);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active { transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
form {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&.auth-form {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-cancel-form {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.auth-cancel {
|
||||||
|
flex: 1;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-cancel-standalone {
|
||||||
|
margin-top: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-cancel--block {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-switch {
|
||||||
|
font: 400 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.35);
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 24px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #95cff5;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover { color: #c5e8ff; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-forgot-password {
|
||||||
|
font: 400 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.35);
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #95cff5;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover { color: #c5e8ff; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-divider::before,
|
||||||
|
.auth-divider::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-divider span {
|
||||||
|
margin: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-passkey-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-passkey-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-passkey-btn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-input--code {
|
||||||
|
font: 700 22px 'Courier New', monospace;
|
||||||
|
letter-spacing: 6px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-field-hint {
|
||||||
|
font: 400 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.45);
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
margin: 6px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-card--wide {
|
||||||
|
max-width: 520px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-back {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font: 500 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.5);
|
||||||
|
text-decoration: none;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover { color: rgba(149, 207, 245, 0.9); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twofa-setup {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
&__qr {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.3);
|
||||||
|
background: #fff;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__manual {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__manual-label {
|
||||||
|
font: 400 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.45);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__secret {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 14px;
|
||||||
|
background: rgba(0, 0, 0, 0.35);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.3);
|
||||||
|
border-radius: 4px;
|
||||||
|
font: 700 14px 'Courier New', monospace;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
color: #95cff5;
|
||||||
|
word-break: break-all;
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
assets/css/homepage/_content.scss
Normal file
35
assets/css/homepage/_content.scss
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
main div.txt {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 60px 40px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt h2 {
|
||||||
|
font: bold 28px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt h3 {
|
||||||
|
font: bold 17px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
margin: 28px 0 10px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt p,
|
||||||
|
main div.txt li {
|
||||||
|
font: 400 15px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.72);
|
||||||
|
line-height: 1.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt a {
|
||||||
|
color: #95cff5;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover { color: #c5e8ff; }
|
||||||
|
}
|
||||||
75
assets/css/homepage/_cta.scss
Normal file
75
assets/css/homepage/_cta.scss
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
.hero-cta {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
font: 800 28px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 22px 100px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(246, 125, 82, 0.25);
|
||||||
|
|
||||||
|
background: linear-gradient(to bottom, #b30c06 0%, #d63d15 50%, #f67d52 100%);
|
||||||
|
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px rgba(173, 10, 5, 0.2),
|
||||||
|
0 0 30px rgba(173, 10, 5, 0.35),
|
||||||
|
0 6px 24px rgba(0, 0, 0, 0.5),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
||||||
|
|
||||||
|
transition: transform 220ms ease, box-shadow 220ms ease, letter-spacing 220ms ease;
|
||||||
|
animation: rise 0.8s 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer glow layer (blurred duplicate, always visible)
|
||||||
|
.hero-cta::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: -4px;
|
||||||
|
border-radius: 7px;
|
||||||
|
background: linear-gradient(to bottom, #ad0a05, #f67d52);
|
||||||
|
filter: blur(18px);
|
||||||
|
opacity: 0.3;
|
||||||
|
z-index: -1;
|
||||||
|
transition: opacity 220ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
letter-spacing: 8px;
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px rgba(246, 125, 82, 0.3),
|
||||||
|
0 0 50px rgba(173, 10, 5, 0.65),
|
||||||
|
0 10px 32px rgba(0, 0, 0, 0.45),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta:hover::before {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta:active {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version / copyright line
|
||||||
|
.hero-meta {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
font: 400 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-top: 58px;
|
||||||
|
animation: rise 0.8s 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-meta a {
|
||||||
|
color: rgba(149, 207, 245, 0.65);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 180ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-meta a:hover {
|
||||||
|
color: #95cff5;
|
||||||
|
}
|
||||||
202
assets/css/homepage/_features.scss
Normal file
202
assets/css/homepage/_features.scss
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
.feature-block {
|
||||||
|
width: 100%;
|
||||||
|
padding: 80px 40px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
border-top: 1px solid rgba(35, 111, 135, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__inner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 80px;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block--reverse .feature-block__inner {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visual side
|
||||||
|
.feature-block__visual {
|
||||||
|
flex: 0 0 340px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stats icons cluster
|
||||||
|
.feature-block__visual--stats {
|
||||||
|
height: 260px;
|
||||||
|
gap: 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
position: absolute;
|
||||||
|
color: rgba(35, 111, 135, 0.5);
|
||||||
|
transition: color 300ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bar chart — large, centre
|
||||||
|
i.fa-bar-chart {
|
||||||
|
font-size: 140px;
|
||||||
|
color: rgba(35, 111, 135, 0.35);
|
||||||
|
filter: drop-shadow(0 0 30px rgba(35, 111, 135, 0.3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trophy — top right
|
||||||
|
i.fa-trophy {
|
||||||
|
font-size: 64px;
|
||||||
|
top: 12px;
|
||||||
|
right: 30px;
|
||||||
|
color: rgba(246, 125, 82, 0.5);
|
||||||
|
filter: drop-shadow(0 0 16px rgba(246, 125, 82, 0.25));
|
||||||
|
}
|
||||||
|
|
||||||
|
// History — bottom left
|
||||||
|
i.fa-history {
|
||||||
|
font-size: 52px;
|
||||||
|
bottom: 18px;
|
||||||
|
left: 30px;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
filter: drop-shadow(0 0 12px rgba(149, 207, 245, 0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover i.fa-bar-chart { color: rgba(35, 111, 135, 0.6); }
|
||||||
|
&:hover i.fa-trophy { color: rgba(246, 125, 82, 0.75); }
|
||||||
|
&:hover i.fa-history { color: rgba(149, 207, 245, 0.65); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSN visual
|
||||||
|
.feature-block__visual--msn {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msn-logo {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
object-fit: contain;
|
||||||
|
filter: drop-shadow(0 0 18px rgba(149, 207, 245, 0.3)) brightness(1.1);
|
||||||
|
flex-shrink: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msn-screenshot {
|
||||||
|
width: 340px;
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
box-shadow:
|
||||||
|
0 8px 40px rgba(0, 0, 0, 0.6),
|
||||||
|
0 0 0 1px rgba(35, 111, 135, 0.12);
|
||||||
|
filter: saturate(0.85) brightness(0.9);
|
||||||
|
transition: filter 300ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: saturate(1) brightness(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text side
|
||||||
|
.feature-block__text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__label {
|
||||||
|
font: 700 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__title {
|
||||||
|
font: 800 40px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__body {
|
||||||
|
font: 400 16px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.62);
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__cta {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 28px;
|
||||||
|
font: 700 14px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgba(149, 207, 245, 0.85);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.4);
|
||||||
|
background: rgba(35, 111, 135, 0.1);
|
||||||
|
padding: 11px 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(35, 111, 135, 0.25);
|
||||||
|
border-color: rgba(149, 207, 245, 0.55);
|
||||||
|
color: #fff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 16px rgba(35, 111, 135, 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.feature-block__inner,
|
||||||
|
.feature-block--reverse .feature-block__inner {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 48px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__visual {
|
||||||
|
flex: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__visual--stats {
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__visual--msn {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msn-screenshot {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__label,
|
||||||
|
.feature-block__cta {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-block__title { font-size: 32px; }
|
||||||
|
|
||||||
|
.feature-block {
|
||||||
|
padding: 60px 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
115
assets/css/homepage/_footer.scss
Normal file
115
assets/css/homepage/_footer.scss
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
footer {
|
||||||
|
background: #040608;
|
||||||
|
border-top: 1px solid rgba(35, 111, 135, 0.12);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-inner {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 60px 60px 52px;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left: brand block
|
||||||
|
.footer-brand {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo {
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
opacity: 0.55;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 12px rgba(35, 111, 135, 0.4))
|
||||||
|
brightness(1.1);
|
||||||
|
transition: opacity 250ms ease, filter 250ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 20px rgba(35, 111, 135, 0.65))
|
||||||
|
brightness(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-name {
|
||||||
|
font: 700 22px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tagline {
|
||||||
|
font: 400 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.7);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
max-width: 240px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right: navigation
|
||||||
|
.footer-nav-label {
|
||||||
|
font: 700 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
margin-bottom: 18px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 6px;
|
||||||
|
min-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav ul li a {
|
||||||
|
display: block;
|
||||||
|
font: 500 15px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
text-decoration: none;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 6px 0;
|
||||||
|
transition: color 180ms ease, letter-spacing 180ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #95cff5;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom copyright bar
|
||||||
|
.footer-copy {
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
padding: 16px 60px;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font: 400 11px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover { color: #95cff5; }
|
||||||
|
}
|
||||||
|
}
|
||||||
39
assets/css/homepage/_header.scss
Normal file
39
assets/css/homepage/_header.scss
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
header {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// Minesweeper grid texture
|
||||||
|
background-color: #07090d;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(rgba(35, 111, 135, 0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(35, 111, 135, 0.1) 1px, transparent 1px);
|
||||||
|
background-size: 46px 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep radial vignette – grid fades toward the centre
|
||||||
|
header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse 85% 75% at 50% 50%,
|
||||||
|
#07090d 10%,
|
||||||
|
transparent 75%
|
||||||
|
);
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smoke at the bottom so header bleeds into body
|
||||||
|
header::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
background: linear-gradient(to bottom, transparent, #07090d);
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
49
assets/css/homepage/_hero-compact.scss
Normal file
49
assets/css/homepage/_hero-compact.scss
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
.hero--compact {
|
||||||
|
min-height: unset;
|
||||||
|
padding: 36px 60px 48px;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: left;
|
||||||
|
gap: 52px;
|
||||||
|
|
||||||
|
&::before, &::after { display: none; }
|
||||||
|
|
||||||
|
.hero-logo {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
img { width: 180px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-body {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-sub {
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 26px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta {
|
||||||
|
padding: 12px 52px 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-meta {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also shrink the bottom fade on sub-pages
|
||||||
|
header:has(.hero--compact)::after {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
90
assets/css/homepage/_hero.scss
Normal file
90
assets/css/homepage/_hero.scss
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 80px 40px 160px;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decorative glow blobs in opposite corners
|
||||||
|
.hero::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -60px;
|
||||||
|
left: -60px;
|
||||||
|
width: 420px;
|
||||||
|
height: 420px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle, rgba(173, 10, 5, 0.09) 0%, transparent 65%);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100px;
|
||||||
|
right: -60px;
|
||||||
|
width: 380px;
|
||||||
|
height: 380px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle, rgba(35, 111, 135, 0.1) 0%, transparent 65%);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logo
|
||||||
|
.hero-logo {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 72px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
animation: appear 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-logo img {
|
||||||
|
width: 400px;
|
||||||
|
max-width: 82vw;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 40px rgba(35, 111, 135, 0.35))
|
||||||
|
drop-shadow(0 6px 20px rgba(0, 0, 0, 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body text block
|
||||||
|
.hero-body {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-sub {
|
||||||
|
font: 300 17px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
letter-spacing: 3px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
animation: rise 0.8s 0.15s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-sub strong {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #95cff5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font: 800 58px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-bottom: 56px;
|
||||||
|
text-shadow: 0 4px 30px rgba(0, 0, 0, 0.7);
|
||||||
|
animation: rise 0.8s 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
891
assets/css/homepage/_profile.scss
Normal file
891
assets/css/homepage/_profile.scss
Normal file
@@ -0,0 +1,891 @@
|
|||||||
|
/*!*
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.profile-page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 48px 24px 80px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 28px;
|
||||||
|
padding: 32px 36px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.2);
|
||||||
|
border-radius: 10px;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
box-shadow: 0 8px 48px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-avatar {
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.45) 0%, rgba(173, 10, 5, 0.3) 100%);
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.45);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font: 800 28px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
box-shadow: 0 0 0 4px rgba(35, 111, 135, 0.08), 0 0 24px rgba(35, 111, 135, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: box-shadow 200ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 4px rgba(35, 111, 135, 0.18), 0 0 32px rgba(35, 111, 135, 0.4);
|
||||||
|
|
||||||
|
.profile-avatar__overlay {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--loading {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__initials {
|
||||||
|
font: 800 28px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.55);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 200ms ease;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-name {
|
||||||
|
font: 800 32px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-email {
|
||||||
|
font: 400 14px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-role {
|
||||||
|
font: 600 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2.5px;
|
||||||
|
color: rgba(255, 255, 255, 0.25);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stats {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat {
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.07);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px 16px 20px;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
transition: border-color 200ms ease, background 200ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border-color: rgba(35, 111, 135, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--win {
|
||||||
|
border-color: rgba(42, 158, 96, 0.18);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(42, 158, 96, 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--loss {
|
||||||
|
border-color: rgba(173, 10, 5, 0.18);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(173, 10, 5, 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--bomb {
|
||||||
|
border-color: rgba(246, 125, 82, 0.18);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(246, 125, 82, 0.45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--draw {
|
||||||
|
border-color: rgba(149, 207, 245, 0.15);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(149, 207, 245, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--rate {
|
||||||
|
border-color: rgba(168, 130, 255, 0.18);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(168, 130, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--avg {
|
||||||
|
border-color: rgba(80, 200, 220, 0.18);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(80, 200, 220, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--best {
|
||||||
|
border-color: rgba(255, 215, 0, 0.15);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(255, 215, 0, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat__icon {
|
||||||
|
font-size: 18px;
|
||||||
|
color: rgba(255, 255, 255, 0.15);
|
||||||
|
margin-bottom: 2px;
|
||||||
|
|
||||||
|
.profile-stat--win & {
|
||||||
|
color: rgba(94, 232, 154, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--loss & {
|
||||||
|
color: rgba(246, 125, 82, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--bomb & {
|
||||||
|
color: rgba(246, 125, 82, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--draw & {
|
||||||
|
color: rgba(149, 207, 245, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--rate & {
|
||||||
|
color: rgba(168, 130, 255, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--avg & {
|
||||||
|
color: rgba(80, 200, 220, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--best & {
|
||||||
|
color: rgba(255, 215, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat__value {
|
||||||
|
display: block;
|
||||||
|
font: 800 40px 'Rajdhani', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
.profile-stat--win & {
|
||||||
|
color: #5ee89a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--loss & {
|
||||||
|
color: #f67d52;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--bomb & {
|
||||||
|
color: rgba(246, 125, 82, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--draw & {
|
||||||
|
color: #95cff5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--rate & {
|
||||||
|
color: #c8a8ff;
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 0.55em;
|
||||||
|
opacity: 0.7;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--avg & {
|
||||||
|
color: #50c8dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat--best & {
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stat__label {
|
||||||
|
font: 600 10px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-action-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 9px 18px;
|
||||||
|
background: rgba(35, 111, 135, 0.12);
|
||||||
|
color: rgba(149, 207, 245, 0.75);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.3);
|
||||||
|
border-radius: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
font: 600 12px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
transition: background 200ms ease, border-color 200ms ease, color 200ms ease;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(35, 111, 135, 0.22);
|
||||||
|
border-color: rgba(35, 111, 135, 0.55);
|
||||||
|
color: rgba(149, 207, 245, 1);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-section__description {
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(149, 207, 245, 0.65);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-section__title {
|
||||||
|
font: 700 18px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(149, 207, 245, 0.45);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-games {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 26px 76px 22px 1fr 18px auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 11px 16px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.025);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.055);
|
||||||
|
border-left-width: 3px;
|
||||||
|
font: 500 14px 'Rajdhani', sans-serif;
|
||||||
|
transition: background 180ms ease, border-color 180ms ease;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.055);
|
||||||
|
border-color: rgba(35, 111, 135, 0.35);
|
||||||
|
border-left-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--win {
|
||||||
|
border-left-color: rgba(42, 158, 96, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--loss {
|
||||||
|
border-left-color: rgba(173, 10, 5, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--draw {
|
||||||
|
border-left-color: rgba(149, 207, 245, 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__badge {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font: 800 10px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0;
|
||||||
|
|
||||||
|
.profile-game--win & {
|
||||||
|
background: rgba(42, 158, 96, 0.18);
|
||||||
|
color: #5ee89a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game--loss & {
|
||||||
|
background: rgba(173, 10, 5, 0.18);
|
||||||
|
color: #f67d52;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game--draw & {
|
||||||
|
background: rgba(149, 207, 245, 0.1);
|
||||||
|
color: rgba(149, 207, 245, 0.65);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__score {
|
||||||
|
font: 700 14px 'Rajdhani', sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__vs {
|
||||||
|
font: 400 10px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.22);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__opponent {
|
||||||
|
color: rgba(149, 207, 245, 0.7);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__color {
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game__date {
|
||||||
|
font: 400 11px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.25);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-charts {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-chart-block {
|
||||||
|
flex: 1 1 300px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.2);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 24px 20px 16px;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
box-shadow: 0 8px 48px rgba(0, 0, 0, 0.4);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.profile-section__title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-chart-inner {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
svg text {
|
||||||
|
font-family: 'Rajdhani', sans-serif !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24px 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-header-left {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-label {
|
||||||
|
font: 600 10px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-title {
|
||||||
|
font: 800 22px 'Rajdhani', sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: rgba(149, 207, 245, 0.5);
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-share {
|
||||||
|
background: rgba(35, 111, 135, 0.12);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.35);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: rgba(149, 207, 245, 0.7);
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font: 600 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
transition: all 180ms ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(35, 111, 135, 0.22);
|
||||||
|
color: #95cff5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--copied {
|
||||||
|
background: rgba(42, 158, 96, 0.15);
|
||||||
|
border-color: rgba(42, 158, 96, 0.4);
|
||||||
|
color: #5ee89a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-close {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 180ms ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-vs-panel {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28px 32px 24px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-vs-center {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-vs-label {
|
||||||
|
font: 800 11px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-vs-score {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
&__red, &__blue {
|
||||||
|
font: 800 52px 'Rajdhani', sans-serif;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__red { color: #f67d52; text-shadow: 0 0 24px rgba(173, 10, 5, 0.5); }
|
||||||
|
&__blue { color: #95cff5; text-shadow: 0 0 24px rgba(35, 111, 135, 0.5); }
|
||||||
|
|
||||||
|
&__sep {
|
||||||
|
font: 800 32px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.2);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-result-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font: 700 12px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-stats {
|
||||||
|
padding: 0 24px 24px;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
|
margin-top: 4px;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-empty {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 20px;
|
||||||
|
color: rgba(255, 255, 255, 0.25);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 40px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font: 400 15px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #95cff5;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: color 180ms;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #c5e8ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 48px 20px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 560px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.25);
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8px 64px rgba(0, 0, 0, 0.6);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
|
||||||
|
&__eyebrow {
|
||||||
|
padding: 18px 28px 0;
|
||||||
|
font: 600 10px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-vs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24px 28px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-player {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
font: 700 16px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 120px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__side {
|
||||||
|
font: 600 10px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--red .bshare-player__name { color: #f67d52; }
|
||||||
|
&--blue .bshare-player__name { color: #95cff5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-avatar {
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font: 800 24px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
|
||||||
|
&--red {
|
||||||
|
background: linear-gradient(135deg, rgba(173, 10, 5, 0.6) 0%, rgba(246, 125, 82, 0.4) 100%);
|
||||||
|
border: 2px solid rgba(173, 10, 5, 0.5);
|
||||||
|
box-shadow: 0 0 0 3px rgba(173, 10, 5, 0.12), 0 0 28px rgba(173, 10, 5, 0.3);
|
||||||
|
color: #f67d52;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--blue {
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.6) 0%, rgba(41, 128, 185, 0.4) 100%);
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.5);
|
||||||
|
box-shadow: 0 0 0 3px rgba(35, 111, 135, 0.12), 0 0 28px rgba(35, 111, 135, 0.3);
|
||||||
|
color: #95cff5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-vs__center {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-vs__label {
|
||||||
|
font: 800 11px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(255, 255, 255, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-score {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
&__red, &__blue {
|
||||||
|
font: 800 56px 'Rajdhani', sans-serif;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__red { color: #f67d52; text-shadow: 0 0 24px rgba(173, 10, 5, 0.5); }
|
||||||
|
&__blue { color: #95cff5; text-shadow: 0 0 24px rgba(35, 111, 135, 0.5); }
|
||||||
|
|
||||||
|
&__sep {
|
||||||
|
font: 800 32px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.18);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--na {
|
||||||
|
font: 800 40px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font: 700 12px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
|
||||||
|
&--red { background: rgba(173, 10, 5, 0.15); border: 1px solid rgba(173, 10, 5, 0.4); color: #f67d52; }
|
||||||
|
&--blue { background: rgba(35, 111, 135, 0.15); border: 1px solid rgba(35, 111, 135, 0.4); color: #95cff5; }
|
||||||
|
&--draw { background: rgba(149, 207, 245, 0.08); border: 1px solid rgba(149, 207, 245, 0.3); color: #95cff5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-details {
|
||||||
|
padding: 16px 28px;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-detail {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font: 500 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
|
||||||
|
i {
|
||||||
|
width: 14px;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--bomb {
|
||||||
|
color: rgba(246, 125, 82, 0.7);
|
||||||
|
|
||||||
|
i { color: rgba(246, 125, 82, 0.5); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-cta {
|
||||||
|
padding: 20px 28px 28px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bshare-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 11px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font: 700 13px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
|
||||||
|
background: linear-gradient(to bottom, #ad0a05 0%, #d4401a 55%, #f67d52 100%);
|
||||||
|
border: 1px solid rgba(246, 125, 82, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 4px 20px rgba(173, 10, 5, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 6px 28px rgba(173, 10, 5, 0.55);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--ghost {
|
||||||
|
background: rgba(255, 255, 255, 0.04);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
assets/css/homepage/_reset.scss
Normal file
23
assets/css/homepage/_reset.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
* {
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
// Grid lives on html so it tiles across all pages including content pages
|
||||||
|
background-color: #07090d;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(rgba(35, 111, 135, 0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(35, 111, 135, 0.1) 1px, transparent 1px);
|
||||||
|
background-size: 46px 46px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: transparent;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
100
assets/css/homepage/_responsive.scss
Normal file
100
assets/css/homepage/_responsive.scss
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta {
|
||||||
|
padding: 20px 72px 18px;
|
||||||
|
font-size: 24px;
|
||||||
|
letter-spacing: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.hero--compact {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
padding: 36px 24px 44px;
|
||||||
|
gap: 28px;
|
||||||
|
|
||||||
|
.hero-body { align-items: center; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stats {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-header {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
padding: 28px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-email,
|
||||||
|
.profile-role {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-game {
|
||||||
|
grid-template-columns: 26px 64px 18px 1fr 14px;
|
||||||
|
|
||||||
|
.profile-game__date { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-inner {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 30px 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-brand {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tagline {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav-label {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav ul {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-copy {
|
||||||
|
padding: 16px 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 550px) {
|
||||||
|
.hero {
|
||||||
|
padding: 60px 24px 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-logo img {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-logo {
|
||||||
|
margin-bottom: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-sub {
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta {
|
||||||
|
padding: 18px 48px 16px;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
assets/css/homepage/_tech.scss
Normal file
60
assets/css/homepage/_tech.scss
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
main {
|
||||||
|
background: #07090d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-section {
|
||||||
|
padding: 48px 20px 72px;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-label {
|
||||||
|
font: 600 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 6px;
|
||||||
|
color: rgba(255, 255, 255, 0.14);
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-link {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-logos img {
|
||||||
|
display: inline-block;
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
object-fit: contain;
|
||||||
|
margin: 8px 24px;
|
||||||
|
// Force all logos to white, then tint with the game's blue on hover
|
||||||
|
filter: brightness(0) invert(1) opacity(0.35);
|
||||||
|
transition: filter 220ms ease, transform 220ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-logos img:hover {
|
||||||
|
filter:
|
||||||
|
brightness(0) invert(1)
|
||||||
|
sepia(1) saturate(3) hue-rotate(175deg) brightness(1.1)
|
||||||
|
opacity(0.9);
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-oss {
|
||||||
|
margin-top: 36px;
|
||||||
|
font: 400 15px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
max-width: 680px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding: 0 24px;
|
||||||
|
line-height: 1.7;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: rgba(220, 60, 50, 0.85);
|
||||||
|
margin-right: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
assets/css/mineseeker/_back-button.scss
Normal file
24
assets/css/mineseeker/_back-button.scss
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.back-from-game {
|
||||||
|
display: inline-block;
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
|
||||||
|
-ms-transform: scale(1);
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
-webkit-transition: all 250ms cubic-bezier(.17, .67, .83, .67);
|
||||||
|
transition: all 250ms cubic-bezier(.17, .67, .83, .67);
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-from-game img {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-from-game:hover {
|
||||||
|
-ms-transform: scale(1.2);
|
||||||
|
-webkit-transform: scale(1.2);
|
||||||
|
transform: scale(1.2);
|
||||||
|
-webkit-transition: all 250ms cubic-bezier(.17, .67, .83, .67);
|
||||||
|
transition: all 250ms cubic-bezier(.17, .67, .83, .67);
|
||||||
|
}
|
||||||
57
assets/css/mineseeker/_base.scss
Normal file
57
assets/css/mineseeker/_base.scss
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-container {
|
||||||
|
background: url("/images/bg-mineseeker-0-outbg.jpg") no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper,
|
||||||
|
#mine-wrapper * {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper {
|
||||||
|
display: table;
|
||||||
|
width: 842px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper {
|
||||||
|
background: #000;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
225
assets/css/mineseeker/_bomb.scss
Normal file
225
assets/css/mineseeker/_bomb.scss
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control {
|
||||||
|
background: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.5) 0%, rgba(125, 185, 232, 0) 100%);
|
||||||
|
background: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.5) 0%, rgba(125, 185, 232, 0) 100%);
|
||||||
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.5) 0%, rgba(125, 185, 232, 0) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#007db9e8', GradientType=1);
|
||||||
|
position: relative;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control > img {
|
||||||
|
position: absolute;
|
||||||
|
width: 55px;
|
||||||
|
left: -5px;
|
||||||
|
bottom: 10px;
|
||||||
|
|
||||||
|
-ms-transform: rotate(-15deg);
|
||||||
|
-webkit-transform: rotate(-15deg);
|
||||||
|
transform: rotate(-15deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .user-control-mines {
|
||||||
|
display: inline-block;
|
||||||
|
background: #FFFFFF;
|
||||||
|
font-size: 25px;
|
||||||
|
text-align: center;
|
||||||
|
width: 45px;
|
||||||
|
height: 35px;
|
||||||
|
margin-left: 25px;
|
||||||
|
margin-top: 5px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-control .user-control-mines {
|
||||||
|
color: #1a3955;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-control .user-control-mines {
|
||||||
|
color: #b10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container {
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
width: 65px;
|
||||||
|
height: 45px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
|
||||||
|
-webkit-border-radius: 7px;
|
||||||
|
border-radius: 7px;
|
||||||
|
-webkit-transform: translateZ(0);
|
||||||
|
transform: translateZ(0);
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container.buzz:hover {
|
||||||
|
-webkit-animation-name: hvr-buzz-out;
|
||||||
|
animation-name: hvr-buzz-out;
|
||||||
|
-webkit-animation-duration: 0.75s;
|
||||||
|
animation-duration: 0.75s;
|
||||||
|
-webkit-animation-timing-function: linear;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
-webkit-animation-iteration-count: 1;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes hvr-buzz-out {
|
||||||
|
10% { -webkit-transform: translateX(3px) rotate(2deg); transform: translateX(3px) rotate(2deg); }
|
||||||
|
20% { -webkit-transform: translateX(-3px) rotate(-2deg); transform: translateX(-3px) rotate(-2deg); }
|
||||||
|
30% { -webkit-transform: translateX(3px) rotate(2deg); transform: translateX(3px) rotate(2deg); }
|
||||||
|
40% { -webkit-transform: translateX(-3px) rotate(-2deg); transform: translateX(-3px) rotate(-2deg); }
|
||||||
|
50% { -webkit-transform: translateX(2px) rotate(1deg); transform: translateX(2px) rotate(1deg); }
|
||||||
|
60% { -webkit-transform: translateX(-2px) rotate(-1deg); transform: translateX(-2px) rotate(-1deg); }
|
||||||
|
70% { -webkit-transform: translateX(2px) rotate(1deg); transform: translateX(2px) rotate(1deg); }
|
||||||
|
80% { -webkit-transform: translateX(-2px) rotate(-1deg); transform: translateX(-2px) rotate(-1deg); }
|
||||||
|
90% { -webkit-transform: translateX(1px) rotate(0); transform: translateX(1px) rotate(0); }
|
||||||
|
100% { -webkit-transform: translateX(-1px) rotate(0); transform: translateX(-1px) rotate(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hvr-buzz-out {
|
||||||
|
10% { -webkit-transform: translateX(3px) rotate(2deg); transform: translateX(3px) rotate(2deg); }
|
||||||
|
20% { -webkit-transform: translateX(-3px) rotate(-2deg); transform: translateX(-3px) rotate(-2deg); }
|
||||||
|
30% { -webkit-transform: translateX(3px) rotate(2deg); transform: translateX(3px) rotate(2deg); }
|
||||||
|
40% { -webkit-transform: translateX(-3px) rotate(-2deg); transform: translateX(-3px) rotate(-2deg); }
|
||||||
|
50% { -webkit-transform: translateX(2px) rotate(1deg); transform: translateX(2px) rotate(1deg); }
|
||||||
|
60% { -webkit-transform: translateX(-2px) rotate(-1deg); transform: translateX(-2px) rotate(-1deg); }
|
||||||
|
70% { -webkit-transform: translateX(2px) rotate(1deg); transform: translateX(2px) rotate(1deg); }
|
||||||
|
80% { -webkit-transform: translateX(-2px) rotate(-1deg); transform: translateX(-2px) rotate(-1deg); }
|
||||||
|
90% { -webkit-transform: translateX(1px) rotate(0); transform: translateX(1px) rotate(0); }
|
||||||
|
100% { -webkit-transform: translateX(-1px) rotate(0); transform: translateX(-1px) rotate(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container .bomb {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container .bomb img {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container:hover .bomb img {
|
||||||
|
-webkit-animation-name: hvr-buzz;
|
||||||
|
animation-name: hvr-buzz;
|
||||||
|
-webkit-animation-duration: 0.15s;
|
||||||
|
animation-duration: 0.15s;
|
||||||
|
-webkit-animation-timing-function: linear;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
-webkit-animation-iteration-count: infinite;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-control .bomb-container .bomb {
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-control .bomb-container .bomb {
|
||||||
|
background: rgb(131, 194, 245);
|
||||||
|
background: -moz-linear-gradient(top, rgba(131, 194, 245, 1) 0%, rgba(108, 190, 230, 1) 39%, rgba(221, 255, 252, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(131, 194, 245, 1) 0%, rgba(108, 190, 230, 1) 39%, rgba(221, 255, 252, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(131, 194, 245, 1) 0%, rgba(108, 190, 230, 1) 39%, rgba(221, 255, 252, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#83c2f5', endColorstr='#ddfffc', GradientType=0);
|
||||||
|
border: 3px solid #0b538e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-control .bomb-container .bomb {
|
||||||
|
background: rgb(255, 175, 159);
|
||||||
|
background: -moz-linear-gradient(top, rgba(255, 175, 159, 1) 0%, rgba(231, 113, 7, 1) 54%, rgba(231, 113, 7, 1) 54%, rgba(237, 172, 16, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(255, 175, 159, 1) 0%, rgba(231, 113, 7, 1) 54%, rgba(231, 113, 7, 1) 54%, rgba(237, 172, 16, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(255, 175, 159, 1) 0%, rgba(231, 113, 7, 1) 54%, rgba(231, 113, 7, 1) 54%, rgba(237, 172, 16, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffaf9f', endColorstr='#edac10', GradientType=0);
|
||||||
|
border: 3px solid #c9221c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resign button
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign {
|
||||||
|
background: rgba(70, 73, 66, 1);
|
||||||
|
background: -moz-linear-gradient(top, rgba(70, 73, 66, 1) 0%, rgba(140, 138, 139, 1) 69%, rgba(96, 89, 97, 1) 100%);
|
||||||
|
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(70, 73, 66, 1)), color-stop(69%, rgba(140, 138, 139, 1)), color-stop(100%, rgba(96, 89, 97, 1)));
|
||||||
|
background: -webkit-linear-gradient(top, rgba(70, 73, 66, 1) 0%, rgba(140, 138, 139, 1) 69%, rgba(96, 89, 97, 1) 100%);
|
||||||
|
background: -o-linear-gradient(top, rgba(70, 73, 66, 1) 0%, rgba(140, 138, 139, 1) 69%, rgba(96, 89, 97, 1) 100%);
|
||||||
|
background: -ms-linear-gradient(top, rgba(70, 73, 66, 1) 0%, rgba(140, 138, 139, 1) 69%, rgba(96, 89, 97, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(70, 73, 66, 1) 0%, rgba(140, 138, 139, 1) 69%, rgba(96, 89, 97, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#464942', endColorstr='#605961', GradientType=0);
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 95%;
|
||||||
|
height: 50px;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 22px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 40px;
|
||||||
|
border: 3px solid #484742;
|
||||||
|
color: #fff;
|
||||||
|
margin: 10px auto 0 auto;
|
||||||
|
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign:hover {
|
||||||
|
background: rgba(70, 73, 66, 1);
|
||||||
|
color: #FFFFFF;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign.disabled {
|
||||||
|
background: rgba(70, 73, 66, 1);
|
||||||
|
color: #848484;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign.disabled:hover {
|
||||||
|
background: rgba(70, 73, 66, 1);
|
||||||
|
color: #848484;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign .resign-shine {
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
background: -moz-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(0, 0, 0, 0)));
|
||||||
|
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: -o-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: -ms-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#000000', GradientType=0);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 33%;
|
||||||
|
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .resign:hover .resign-shine,
|
||||||
|
#mine-wrapper .game-wrapper .users .resign.disabled .resign-shine {
|
||||||
|
display: none;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
209
assets/css/mineseeker/_grid.scss
Normal file
209
assets/css/mineseeker/_grid.scss
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
#mine-wrapper .grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 643px;
|
||||||
|
border: 1px solid #cac3e5;
|
||||||
|
|
||||||
|
cursor: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid-container {
|
||||||
|
background: #4E4E4E;
|
||||||
|
padding: 15px 10px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-target {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
width: 45px;
|
||||||
|
top: -2.5px;
|
||||||
|
left: -2.5px;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper:hover > img.field-target {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-bomb-target {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-blue-last,
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-red-last {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-blue-last.last-clicked,
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-red-last.last-clicked {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field {
|
||||||
|
background: #61defa;
|
||||||
|
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 2px solid #51c2fe;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 35px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field .field-corner {
|
||||||
|
background: url('/images/bg-corner-outbg.png') no-repeat top left;
|
||||||
|
background-size: 100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active {
|
||||||
|
background: #fde717;
|
||||||
|
background: -moz-linear-gradient(left, #fde717 0%, #f5b807 100%);
|
||||||
|
background: -webkit-linear-gradient(left, #fde717 0%, #f5b807 100%);
|
||||||
|
background: linear-gradient(to right, #fde717 0%, #f5b807 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fde717', endColorstr='#f5b807', GradientType=1);
|
||||||
|
border: 2px solid #f6d762;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active .flag-number {
|
||||||
|
-webkit-animation: bubbleNumber 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
animation: bubbleNumber 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bubbleNumber {
|
||||||
|
0% {
|
||||||
|
background: #61defa;
|
||||||
|
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
|
||||||
|
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active .flag-mine {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active .flag-mine > img {
|
||||||
|
width: 75%;
|
||||||
|
margin-left: 15px;
|
||||||
|
|
||||||
|
-ms-transform: rotate(7deg);
|
||||||
|
-webkit-transform: rotate(7deg);
|
||||||
|
transform: rotate(7deg);
|
||||||
|
-webkit-animation: mineFlagLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
animation: mineFlagLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mineFlagLoad {
|
||||||
|
0% {
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 15px;
|
||||||
|
-ms-transform: rotate(9deg);
|
||||||
|
-webkit-transform: rotate(9deg);
|
||||||
|
transform: rotate(9deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
margin-bottom: -5px;
|
||||||
|
margin-left: 7px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
margin-left: 0;
|
||||||
|
-ms-transform: rotate(-9deg);
|
||||||
|
-webkit-transform: rotate(-9deg);
|
||||||
|
transform: rotate(-9deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active .flag-mine .flag-mine-base {
|
||||||
|
position: absolute;
|
||||||
|
background: #000000;
|
||||||
|
width: 25px;
|
||||||
|
height: 22px;
|
||||||
|
bottom: -12px;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -10.5px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
-webkit-animation: mineBaseLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
animation: mineBaseLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mineBaseLoad {
|
||||||
|
0% { margin-bottom: 0; }
|
||||||
|
50% { margin-bottom: -5px; }
|
||||||
|
100% { margin-bottom: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.mine {
|
||||||
|
background: #61defa;
|
||||||
|
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
|
||||||
|
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
|
||||||
|
border: 2px solid #51c2fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-1 { color: #0000ff; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-2 { color: #079433; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-3 { color: #fd1400; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-4 { color: #0c099e; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-5 { color: #7b4c01; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-6 { color: #008388; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-7 { color: #000000; }
|
||||||
|
#mine-wrapper .grid .field-wrapper .field.active.color-8 { color: #ff0000; }
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field img {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
90
assets/css/mineseeker/_mine-counter.scss
Normal file
90
assets/css/mineseeker/_mine-counter.scss
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container {
|
||||||
|
background: -moz-radial-gradient(center, ellipse cover, rgba(255, 252, 252, 1) 0%, rgba(255, 252, 252, 0.99) 1%, rgba(106, 106, 106, 0.39) 61%, rgba(106, 106, 106, 0) 100%);
|
||||||
|
background: -webkit-radial-gradient(center, ellipse cover, rgba(255, 252, 252, 1) 0%, rgba(255, 252, 252, 0.99) 1%, rgba(106, 106, 106, 0.39) 61%, rgba(106, 106, 106, 0) 100%);
|
||||||
|
background: radial-gradient(ellipse at center, rgba(255, 252, 252, 1) 0%, rgba(255, 252, 252, 0.99) 1%, rgba(106, 106, 106, 0.39) 61%, rgba(106, 106, 106, 0) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcfc', endColorstr='#006a6a6a', GradientType=1);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: 72% 179%;
|
||||||
|
position: relative;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container i {
|
||||||
|
font-size: 27px;
|
||||||
|
color: #b1b1b3;
|
||||||
|
margin-top: 3px;
|
||||||
|
|
||||||
|
text-shadow: 0 0 3px #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container i:first-child {
|
||||||
|
float: left;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container i:last-child {
|
||||||
|
float: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container .active-mines {
|
||||||
|
background: -moz-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(135, 136, 131, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(135, 136, 131, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(135, 136, 131, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3e3f41', endColorstr='#878883', GradientType=0);
|
||||||
|
position: absolute;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
top: -7.5px;
|
||||||
|
left: 50%;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 39px;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
border: 5px solid #000000;
|
||||||
|
margin-left: -25px;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container .active-mines.found-mine {
|
||||||
|
-webkit-animation: bubbleLeftMine 750ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
animation: bubbleLeftMine 750ms cubic-bezier(.36, .07, .19, .97) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bubbleLeftMine {
|
||||||
|
0% { -webkit-transform: scale(1); transform: scale(1); }
|
||||||
|
50% { border-color: #2e3337; -webkit-transform: scale(2); transform: scale(2); }
|
||||||
|
100% { -webkit-transform: scale(1); transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container .active-mines .active-mines-shine {
|
||||||
|
background: -moz-linear-gradient(top, rgba(213, 214, 216, 1) 0%, rgba(106, 106, 106, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(213, 214, 216, 1) 0%, rgba(106, 106, 106, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(213, 214, 216, 1) 0%, rgba(106, 106, 106, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d5d6d8', endColorstr='#6a6a6a', GradientType=0);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
width: 30px;
|
||||||
|
height: 20px;
|
||||||
|
margin-left: -14.5px;
|
||||||
|
|
||||||
|
z-index: 101;
|
||||||
|
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .active-mines-container .active-mines .active-mines-nbr {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
z-index: 102;
|
||||||
|
}
|
||||||
528
assets/css/mineseeker/_overlay.scss
Normal file
528
assets/css/mineseeker/_overlay.scss
Normal file
@@ -0,0 +1,528 @@
|
|||||||
|
#mine-wrapper .game-wrapper .game-overlay {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window {
|
||||||
|
background: linear-gradient(135deg, rgba(7, 9, 13, 0.98) 0%, rgba(10, 20, 35, 0.98) 100%);
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.4);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
font-family: 'Rajdhani', sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 680px;
|
||||||
|
padding: 40px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.7), 0 0 40px rgba(35, 111, 135, 0.15);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
animation: slideUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window h1 {
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 32px;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0 0 50px 0;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window h2 {
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
margin: 0 0 30px 0;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .resign {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
font-size: inherit;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
background: linear-gradient(to bottom, #236f87 0%, #1a5068 100%);
|
||||||
|
border: 2px solid #2e7a9a;
|
||||||
|
color: #e0f4ff;
|
||||||
|
font: 800 13px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 260px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 12px rgba(35, 111, 135, 0.25);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||||
|
transition: left 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #2d8aa8 0%, #236f87 100%);
|
||||||
|
border-color: #5ba4d4;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 8px 24px rgba(35, 111, 135, 0.4);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
background: linear-gradient(to bottom, #8a2323 0%, #681a1a 100%);
|
||||||
|
border-color: #9a2e2e;
|
||||||
|
color: #ffe0e0;
|
||||||
|
box-shadow: 0 4px 12px rgba(135, 35, 35, 0.25);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #a82d2d 0%, #872323 100%);
|
||||||
|
border-color: #d45b5b;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 8px 24px rgba(135, 35, 35, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window:has(.resign) h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window:has(.resign) h2 {
|
||||||
|
text-align: center;
|
||||||
|
color: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #236f87;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-invite {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-invite-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #386e8c;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting-options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto 1fr;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: stretch;
|
||||||
|
width: 100%;
|
||||||
|
animation: fadeInUp 0.6s ease-out 0.2s both;
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting-option {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 15px;
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.08) 0%, rgba(26, 80, 104, 0.08) 100%);
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.2);
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 350ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
animation: scaleIn 0.5s ease-out;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(35, 111, 135, 0.15), transparent);
|
||||||
|
transition: left 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(35, 111, 135, 0.45);
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.12) 0%, rgba(26, 80, 104, 0.12) 100%);
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 12px 30px rgba(35, 111, 135, 0.2);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting-option-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 17px;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.4) 0%, rgba(35, 111, 135, 0.2) 100%);
|
||||||
|
border: 2px solid rgba(35, 111, 135, 0.5);
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 400ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover i {
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.6) 0%, rgba(35, 111, 135, 0.4) 100%);
|
||||||
|
border-color: rgba(35, 111, 135, 0.8);
|
||||||
|
transform: scale(1.15) rotate(-8deg);
|
||||||
|
box-shadow: 0 0 20px rgba(35, 111, 135, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting-option-desc {
|
||||||
|
font: 600 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.75);
|
||||||
|
margin: 0;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting-divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
margin: 0;
|
||||||
|
animation: slideIn 0.7s ease-out 0.4s both;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 2px;
|
||||||
|
height: 20px;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(35, 111, 135, 0.1),
|
||||||
|
rgba(35, 111, 135, 0.4),
|
||||||
|
rgba(35, 111, 135, 0.1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font: 700 11px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(35, 111, 135, 0.6);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 8px 0;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
width: auto;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(35, 111, 135, 0),
|
||||||
|
rgba(35, 111, 135, 0.3),
|
||||||
|
rgba(35, 111, 135, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-invite {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-url-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #d0e8f5 0%, #c5dff0 100%);
|
||||||
|
border: 2px solid #7ab8d8;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0 10px;
|
||||||
|
cursor: text;
|
||||||
|
transition: all 300ms ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #236f87;
|
||||||
|
box-shadow: 0 4px 12px rgba(35, 111, 135, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border-color: #236f87;
|
||||||
|
box-shadow: 0 0 16px rgba(35, 111, 135, 0.35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-url-icon {
|
||||||
|
color: #236f87;
|
||||||
|
font-size: 13px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-url-input {
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
height: 40px;
|
||||||
|
color: #1a4a6a;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
cursor: text;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
&::selection {
|
||||||
|
background: rgba(35, 111, 135, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scaleIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .browse-players-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
background: linear-gradient(to bottom, #236f87 0%, #1a5068 100%);
|
||||||
|
border: 2px solid #2e7a9a;
|
||||||
|
color: #e0f4ff;
|
||||||
|
font: 700 13px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 800;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 12px rgba(35, 111, 135, 0.25);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||||
|
transition: left 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #2d8aa8 0%, #236f87 100%);
|
||||||
|
border-color: #5ba4d4;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 8px 24px rgba(35, 111, 135, 0.4);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .game-overlay .game-overlay-window .share-copy-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 9px;
|
||||||
|
background: linear-gradient(to bottom, #236f87 0%, #1a5068 100%);
|
||||||
|
border: 2px solid #2e7a9a;
|
||||||
|
color: #e0f4ff;
|
||||||
|
font-family: 'Rajdhani', sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 12px rgba(35, 111, 135, 0.25);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||||
|
transition: left 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(to bottom, #2d8aa8 0%, #236f87 100%);
|
||||||
|
border-color: #5ba4d4;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 8px 24px rgba(35, 111, 135, 0.4);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.copied {
|
||||||
|
background: linear-gradient(to bottom, #1a6844 0%, #135233 100%);
|
||||||
|
border-color: #2a9e60;
|
||||||
|
color: #a0f0c0;
|
||||||
|
box-shadow: 0 4px 12px rgba(26, 104, 68, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
assets/css/mineseeker/_responsive.scss
Normal file
41
assets/css/mineseeker/_responsive.scss
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
#mine-wrapper .game-wrapper .users {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper {
|
||||||
|
width: 6.25%;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper > img.field-target {
|
||||||
|
width: 105%;
|
||||||
|
top: -2.5%;
|
||||||
|
left: -2.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .grid .field-wrapper .field {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
102
assets/css/mineseeker/_timer.scss
Normal file
102
assets/css/mineseeker/_timer.scss
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#mine-wrapper .game-timer-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 115px;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 18px;
|
||||||
|
font-family: 'Rajdhani', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red – waiting
|
||||||
|
#mine-wrapper .game-timer.red-timer {
|
||||||
|
background: linear-gradient(to bottom, #4a0603 0%, #6b2515 100%);
|
||||||
|
border-color: #7a1e10;
|
||||||
|
color: rgba(246, 125, 82, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red – active (thinking)
|
||||||
|
#mine-wrapper .game-timer.red-timer.active {
|
||||||
|
background: linear-gradient(to bottom, #ad0a05 0%, #f67d52 100%);
|
||||||
|
border-color: #ff9b6b;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 16px rgba(173, 10, 5, 0.75), 0 0 5px rgba(246, 125, 82, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blue – waiting
|
||||||
|
#mine-wrapper .game-timer.blue-timer {
|
||||||
|
background: linear-gradient(to bottom, #0b2530 0%, #163d55 100%);
|
||||||
|
border-color: #173650;
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blue – active (thinking)
|
||||||
|
#mine-wrapper .game-timer.blue-timer.active {
|
||||||
|
background: linear-gradient(to bottom, #236f87 0%, #95cff5 100%);
|
||||||
|
border-color: #b8e5ff;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 16px rgba(35, 111, 135, 0.75), 0 0 5px rgba(149, 207, 245, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer .timer-avatar {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: 'Rajdhani', sans-serif;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer .timer-avatar__img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer.red-timer .timer-avatar__initials {
|
||||||
|
color: rgba(246, 125, 82, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer.blue-timer .timer-avatar__initials {
|
||||||
|
color: rgba(149, 207, 245, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer .timer-icon {
|
||||||
|
font-size: 15px;
|
||||||
|
opacity: 0.7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer.active .timer-icon {
|
||||||
|
opacity: 1;
|
||||||
|
animation: timer-icon-pulse 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes timer-icon-pulse {
|
||||||
|
0%, 100% { transform: scale(1); opacity: 0.85; }
|
||||||
|
50% { transform: scale(1.2); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-timer .timer-display {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
153
assets/css/mineseeker/_users.scss
Normal file
153
assets/css/mineseeker/_users.scss
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#mine-wrapper .game-wrapper .users {
|
||||||
|
width: 180px;
|
||||||
|
padding: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container {
|
||||||
|
background: #FFFFFF;
|
||||||
|
height: 40%;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue {
|
||||||
|
background: rgb(35, 111, 135);
|
||||||
|
background: -moz-linear-gradient(top, rgba(35, 111, 135, 1) 0%, rgba(149, 207, 245, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(35, 111, 135, 1) 0%, rgba(149, 207, 245, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(35, 111, 135, 1) 0%, rgba(149, 207, 245, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#236f87', endColorstr='#95cff5', GradientType=0);
|
||||||
|
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red {
|
||||||
|
background: rgb(173, 10, 5);
|
||||||
|
background: -moz-linear-gradient(top, rgba(173, 10, 5, 1) 0%, rgba(246, 125, 82, 1) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(173, 10, 5, 1) 0%, rgba(246, 125, 82, 1) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(173, 10, 5, 1) 0%, rgba(246, 125, 82, 1) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ad0a05', endColorstr='#f67d52', GradientType=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-header {
|
||||||
|
background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.7) 39%, rgba(255, 255, 255, 0.21) 87%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.7) 39%, rgba(255, 255, 255, 0.21) 87%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.7) 39%, rgba(255, 255, 255, 0.21) 87%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#00000000', GradientType=0);
|
||||||
|
position: relative;
|
||||||
|
font: bolder 25px 'Changa One', cursive;
|
||||||
|
letter-spacing: 5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
padding: 6px 5px 20px 5px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-text-shadow: 1px 1px 0 #FFF;
|
||||||
|
text-shadow: 1px 1px 0 #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-header {
|
||||||
|
color: #236f87;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-header {
|
||||||
|
color: #AD0A05;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-header > img {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
width: 40%;
|
||||||
|
margin-left: -20%;
|
||||||
|
margin-bottom: -25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-header > img.user-cursor {
|
||||||
|
display: block;
|
||||||
|
width: 30%;
|
||||||
|
top: 20px;
|
||||||
|
left: 10px;
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
-webkit-animation: cursorJumping 1.2s cubic-bezier(.36, .07, .19, .97) infinite;
|
||||||
|
animation: cursorJumping 1.2s cubic-bezier(.36, .07, .19, .97) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-header > img.user-cursor::after {
|
||||||
|
content: '';
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: #1A6844;
|
||||||
|
animation: animate .5s linear infinite;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cursorJumping {
|
||||||
|
0% { top: 15px; }
|
||||||
|
50% { top: 25px; }
|
||||||
|
100% { top: 15px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-name {
|
||||||
|
min-height: 30px;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
padding: 3px 0;
|
||||||
|
margin: 0 5px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-name {
|
||||||
|
border-top: 1px dashed #0b3776;
|
||||||
|
border-bottom: 1px dashed #0b3776;
|
||||||
|
color: #0b3776;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-name {
|
||||||
|
color: #fdf612;
|
||||||
|
border-top: 1px dashed #fdf612;
|
||||||
|
border-bottom: 1px dashed #fdf612;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-caret {
|
||||||
|
height: 30px;
|
||||||
|
font-size: 30px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-caret > i {
|
||||||
|
color: #0b3776;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-caret > i {
|
||||||
|
color: #fdf612;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container .user-desc {
|
||||||
|
height: 65px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-blue .user-desc {
|
||||||
|
color: #0b3776;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mine-wrapper .game-wrapper .users .user-container.user-red .user-desc {
|
||||||
|
color: #fdf612;
|
||||||
|
}
|
||||||
307
assets/css/mineseeker/_waiting-dialog.scss
Normal file
307
assets/css/mineseeker/_waiting-dialog.scss
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
.opd-paper {
|
||||||
|
background: #07090d !important;
|
||||||
|
background-image: linear-gradient(rgba(35, 111, 135, 0.08) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(35, 111, 135, 0.08) 1px, transparent 1px) !important;
|
||||||
|
background-size: 46px 46px !important;
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.4) !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
box-shadow: 0 0 80px rgba(35, 111, 135, 0.15),
|
||||||
|
0 32px 80px rgba(0, 0, 0, 0.9) !important;
|
||||||
|
width: 500px;
|
||||||
|
max-width: 94vw !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd {
|
||||||
|
padding: 28px 28px 22px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 22px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-header-text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-label {
|
||||||
|
display: block;
|
||||||
|
font: 700 11px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-title {
|
||||||
|
font: 800 28px 'Rajdhani', sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 11px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: rgba(35, 111, 135, 0.9);
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-refresh,
|
||||||
|
.opd-close {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.3);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
border-color: rgba(149, 207, 245, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(35, 111, 135, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-refresh--spin i {
|
||||||
|
animation: opd-spin 0.7s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes opd-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-search-wrap {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: rgba(35, 111, 135, 0.07);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.28);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0 14px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
transition: border-color 200ms ease, background 200ms ease;
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border-color: rgba(35, 111, 135, 0.65);
|
||||||
|
background: rgba(35, 111, 135, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-search-icon {
|
||||||
|
color: rgba(149, 207, 245, 0.38);
|
||||||
|
font-size: 13px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-search {
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
height: 44px;
|
||||||
|
font: 400 14px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(149, 207, 245, 0.32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-search-clear {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
color: rgba(149, 207, 245, 0.4);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 0 0 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: color 150ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgba(149, 207, 245, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-list {
|
||||||
|
min-height: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 30px 0 22px;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 34px;
|
||||||
|
color: rgba(35, 111, 135, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font: 400 14px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 255, 255, 0.38);
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
padding: 11px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all 180ms ease;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(35, 111, 135, 0.1);
|
||||||
|
border-color: rgba(35, 111, 135, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-avatar {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, rgba(35, 111, 135, 0.55) 0%, rgba(35, 111, 135, 0.28) 100%);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font: 700 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
letter-spacing: 1px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-name {
|
||||||
|
font: 700 15px 'Rajdhani', sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-since {
|
||||||
|
font: 400 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.48);
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-join {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: linear-gradient(to bottom, rgba(35, 111, 135, 0.75) 0%, rgba(26, 80, 104, 0.9) 100%);
|
||||||
|
border: 1px solid rgba(35, 111, 135, 0.55);
|
||||||
|
color: rgba(149, 207, 245, 0.9);
|
||||||
|
font: 700 12px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 7px 16px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 200ms ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: linear-gradient(to bottom, rgba(45, 138, 168, 0.9) 0%, rgba(35, 111, 135, 0.95) 100%);
|
||||||
|
border-color: rgba(149, 207, 245, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 14px rgba(35, 111, 135, 0.5);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.opd-join--waiting {
|
||||||
|
background: linear-gradient(to bottom, rgba(26, 80, 104, 0.6) 0%, rgba(15, 50, 70, 0.7) 100%);
|
||||||
|
border-color: rgba(35, 111, 135, 0.3);
|
||||||
|
color: rgba(149, 207, 245, 0.6);
|
||||||
|
opacity: 1;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-declined {
|
||||||
|
font: 600 12px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(255, 120, 120, 0.85);
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid rgba(180, 60, 60, 0.3);
|
||||||
|
background: rgba(180, 60, 60, 0.08);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opd-note {
|
||||||
|
font: 400 11px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.32);
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-top: 14px;
|
||||||
|
padding-top: 14px;
|
||||||
|
border-top: 1px solid rgba(35, 111, 135, 0.14);
|
||||||
|
}
|
||||||
292
assets/css/passkey.scss
Normal file
292
assets/css/passkey.scss
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
@use "sass:color";
|
||||||
|
|
||||||
|
.twofa-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font: 600 13px 'Rajdhani', sans-serif;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
|
||||||
|
&--enabled {
|
||||||
|
background: rgba(42, 158, 96, 0.12);
|
||||||
|
border: 1px solid rgba(42, 158, 96, 0.3);
|
||||||
|
color: #5ee89a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twofa-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&__form {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twofa-backup-meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&__count {
|
||||||
|
font: 500 13px 'Rajdhani', sans-serif;
|
||||||
|
color: rgba(149, 207, 245, 0.55);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twofa-backup-reveal {
|
||||||
|
background: rgba(246, 125, 82, 0.07);
|
||||||
|
border: 1px solid rgba(246, 125, 82, 0.25);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 18px 20px;
|
||||||
|
|
||||||
|
&__warning {
|
||||||
|
font: 600 12px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
color: #f6a060;
|
||||||
|
margin: 0 0 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.twofa-backup-code {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding: 7px 10px;
|
||||||
|
background: rgba(0, 0, 0, 0.35);
|
||||||
|
border: 1px solid rgba(246, 125, 82, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
font: 700 13px 'Courier New', monospace;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: #e0c890;
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
$primary: #236f87;
|
||||||
|
$primary-dark: #1a5a70;
|
||||||
|
$danger: #c0392b;
|
||||||
|
$warning: #d68910;
|
||||||
|
$success: #388e3c;
|
||||||
|
$text: #e0e0e0;
|
||||||
|
$text-muted: #9e9e9e;
|
||||||
|
$border: rgba(35, 111, 135, 0.3);
|
||||||
|
$bg-card: #0a0e14;
|
||||||
|
$bg-hover: rgba(35, 111, 135, 0.15);
|
||||||
|
|
||||||
|
.passkey-manager {
|
||||||
|
&__actions {
|
||||||
|
margin: 20px 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.passkey-item {
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 15px;
|
||||||
|
background: $bg-card;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $bg-hover;
|
||||||
|
border-color: rgba(35, 111, 135, 0.5);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: $text-muted;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__badges {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid $border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
background: rgba(25, 118, 210, 0.2);
|
||||||
|
color: #64b5f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background: rgba(56, 142, 60, 0.2);
|
||||||
|
color: #81c784;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
background: $primary;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $primary-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--secondary {
|
||||||
|
background: #546e7a;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #455a64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
background: $warning;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: color.adjust($warning, $lightness: -10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--danger {
|
||||||
|
background: $danger;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: color.adjust($danger, $lightness: -10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--sm {
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
border: 1px dashed $border;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #455a64;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: $text;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subtext {
|
||||||
|
font-size: 13px;
|
||||||
|
color: $text-muted;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.registration-status {
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background: rgba(56, 142, 60, 0.15);
|
||||||
|
color: #81c784;
|
||||||
|
border: 1px solid rgba(56, 142, 60, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background: rgba(192, 57, 43, 0.15);
|
||||||
|
color: #e57373;
|
||||||
|
border: 1px solid rgba(192, 57, 43, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--loading {
|
||||||
|
background: rgba(25, 118, 210, 0.15);
|
||||||
|
color: #64b5f6;
|
||||||
|
border: 1px solid rgba(25, 118, 210, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
assets/css/style.homepage.scss
Normal file
14
assets/css/style.homepage.scss
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@use 'homepage/reset';
|
||||||
|
@use 'homepage/animations';
|
||||||
|
@use 'homepage/header';
|
||||||
|
@use 'homepage/hero';
|
||||||
|
@use 'homepage/hero-compact';
|
||||||
|
@use 'homepage/cta';
|
||||||
|
@use 'homepage/auth-bar';
|
||||||
|
@use 'homepage/auth';
|
||||||
|
@use 'homepage/content';
|
||||||
|
@use 'homepage/features';
|
||||||
|
@use 'homepage/tech';
|
||||||
|
@use 'homepage/footer';
|
||||||
|
@use 'homepage/profile';
|
||||||
|
@use 'homepage/responsive';
|
||||||
408
assets/css/style.layout.scss
Normal file
408
assets/css/style.layout.scss
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
/*!*
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import 'fonts-config';
|
||||||
|
@import 'fontawesome-config';
|
||||||
|
@import "style";
|
||||||
|
@import "style.homepage";
|
||||||
|
|
||||||
|
::-webkit-input-placeholder {
|
||||||
|
color: #888982;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-placeholder {
|
||||||
|
color: #888982;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-ms-input-placeholder {
|
||||||
|
color: #888982;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-moz-placeholder {
|
||||||
|
color: #888982;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:after,
|
||||||
|
*::before {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ac-custom {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-check {
|
||||||
|
display: table;
|
||||||
|
position: relative;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section h1 {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .input-submit button,
|
||||||
|
header section .input-submit button:hover,
|
||||||
|
header section .form-input,
|
||||||
|
header section .form-input:focus,
|
||||||
|
header section .form-input:hover {
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .input-submit button {
|
||||||
|
background: #83aed9;
|
||||||
|
display: table;
|
||||||
|
font: bold 32px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
width: 500px;
|
||||||
|
border: 1px solid #658fb8;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 25px 150px;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
-webkit-box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
|
||||||
|
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .input-submit button:hover {
|
||||||
|
background: #86b5e1;
|
||||||
|
|
||||||
|
-webkit-box-shadow: 0 7px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0 7px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-input {
|
||||||
|
display: block;
|
||||||
|
width: 500px;
|
||||||
|
font: bold 22px 'Rajdhani', sans-serif;
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
color: #000000;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
||||||
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-input:focus,
|
||||||
|
header section .form-input:hover {
|
||||||
|
-webkit-box-shadow: 0 7px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
box-shadow: 0 7px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure {
|
||||||
|
background: #f00;
|
||||||
|
position: relative;
|
||||||
|
border: 3px solid #fff;
|
||||||
|
font: bold 16px 'Rajdhani', sans-serif;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 30px 0 10px 0;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure:after,
|
||||||
|
header section .failure:before {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50px;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
border: solid transparent;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure:after {
|
||||||
|
border-color: rgba(0, 0, 0, 0);
|
||||||
|
border-bottom-color: #f00;
|
||||||
|
border-width: 20px;
|
||||||
|
margin-left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure:before {
|
||||||
|
border-color: rgba(255, 255, 255, 0);
|
||||||
|
border-bottom-color: #ffffff;
|
||||||
|
border-width: 26px;
|
||||||
|
margin-left: -26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure ul {
|
||||||
|
display: inline-block;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section h3.or {
|
||||||
|
font: bold 16px 'Rajdhani', sans-serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #a1a1a1;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section #id_welcome {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 115px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section #id_welcome > div {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section #id_welcome img {
|
||||||
|
width: 100px;
|
||||||
|
border: 5px solid #414040;
|
||||||
|
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .buttons,
|
||||||
|
header section form {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login,
|
||||||
|
header section div.buttons > a.slack-login {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 500px;
|
||||||
|
height: 93px;
|
||||||
|
padding: 25px 0 25px 150px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
||||||
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login:hover,
|
||||||
|
header section div.buttons > a.slack-login:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
-webkit-box-shadow: 0 7px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
box-shadow: 0 7px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login i,
|
||||||
|
header section div.buttons > a.slack-login i {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 130px;
|
||||||
|
top: 0;
|
||||||
|
left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login {
|
||||||
|
background: #5975b1;
|
||||||
|
border: 1px solid #50649f;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login:hover {
|
||||||
|
background: #42598c;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.slack-login {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid #5c3a58;
|
||||||
|
color: #5c3a58;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.slack-login:hover {
|
||||||
|
background: #e6e6e6;
|
||||||
|
color: #5c3a58;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .failure-main {
|
||||||
|
background: #f00;
|
||||||
|
max-width: 500px;
|
||||||
|
border: 3px solid #fff;
|
||||||
|
font: bold 16px 'Rajdhani', sans-serif;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1000px;
|
||||||
|
font-family: 'Rajdhani', sans-serif;
|
||||||
|
color: #414040;
|
||||||
|
margin: 50px auto 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt h2 {
|
||||||
|
margin: 0 0 50px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt p {
|
||||||
|
font: normal 16px 'Rajdhani', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt li {
|
||||||
|
font: normal 16px 'Rajdhani', sans-serif;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .technologies {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .technologies img {
|
||||||
|
display: inline-block;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 100px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .technologies h1 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background: #414040;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 50px;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul {
|
||||||
|
display: inline-block;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li {
|
||||||
|
display: inline-block;
|
||||||
|
font: bold 16px 'Rajdhani', sans-serif;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li:nth-child(even) {
|
||||||
|
width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li a {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 50px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li a:hover {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1100px) {
|
||||||
|
header section #id_welcome {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-input,
|
||||||
|
header section .form-check {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .input-submit button {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section > div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login,
|
||||||
|
header section div.buttons > a.slack-login {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt {
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 550px) {
|
||||||
|
header section #id_welcome {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .form-check {
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section .input-submit button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login,
|
||||||
|
header section div.buttons > a.slack-login {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section div.buttons > a.fb-login span,
|
||||||
|
header section div.buttons > a.slack-login span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer nav ul li:nth-child(even) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
assets/css/style.mineseeker.scss
Normal file
23
assets/css/style.mineseeker.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*!*
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import "style";
|
||||||
|
@import 'fonts-config';
|
||||||
|
@import 'fontawesome-config';
|
||||||
|
|
||||||
|
@import 'mineseeker/base';
|
||||||
|
@import 'mineseeker/overlay';
|
||||||
|
@import 'mineseeker/users';
|
||||||
|
@import 'mineseeker/bomb';
|
||||||
|
@import 'mineseeker/mine-counter';
|
||||||
|
@import 'mineseeker/grid';
|
||||||
|
@import 'mineseeker/back-button';
|
||||||
|
@import 'mineseeker/timer';
|
||||||
|
@import 'mineseeker/responsive';
|
||||||
|
@import 'mineseeker/waiting-dialog';
|
||||||
10
assets/css/style.scss
Normal file
10
assets/css/style.scss
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.mine-beta {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 150px;
|
||||||
|
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
170
assets/images/waiting-dialog-design.svg
Normal file
170
assets/images/waiting-dialog-design.svg
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<!---
|
||||||
|
- This file is part of the SplendidBear Websites' projects.
|
||||||
|
-
|
||||||
|
- Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
-
|
||||||
|
- For the full copyright and license information, please view the LICENSE
|
||||||
|
- file that was distributed with this source code.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<svg viewBox="0 0 800 500" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.bg-dark { fill: #07090d; }
|
||||||
|
.bg-grid { fill: url(#gridPattern); }
|
||||||
|
.border-accent { stroke: rgba(35, 111, 135, 0.4); stroke-width: 2; fill: none; }
|
||||||
|
.shadow { filter: drop-shadow(0 8px 20px rgba(0, 0, 0, 0.4)); }
|
||||||
|
.title-text { font: bold 28px 'Rajdhani', sans-serif; fill: #fff; letter-spacing: 0.5px; }
|
||||||
|
.header-text { font: bold 16px 'Rajdhani', sans-serif; fill: #236f87; letter-spacing: 0.5px; }
|
||||||
|
.desc-text { font: 13px 'Rajdhani', sans-serif; fill: rgba(149, 207, 245, 0.7); letter-spacing: 0.3px; }
|
||||||
|
.divider-line { stroke: rgba(35, 111, 135, 0.25); stroke-width: 1.5; }
|
||||||
|
.divider-text { font: bold 12px 'Rajdhani', sans-serif; fill: rgba(35, 111, 135, 0.5); letter-spacing: 1px; text-transform: uppercase; }
|
||||||
|
.icon-color { fill: rgba(35, 111, 135, 0.9); }
|
||||||
|
.button-gradient { fill: url(#buttonGradient); }
|
||||||
|
.button-text { font: bold 13px 'Rajdhani', sans-serif; fill: #e0f4ff; letter-spacing: 1.5px; text-transform: uppercase; }
|
||||||
|
.glow { filter: drop-shadow(0 0 12px rgba(35, 111, 135, 0.3)); }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Grid Pattern Background -->
|
||||||
|
<pattern id="gridPattern" x="0" y="0" width="46" height="46" patternUnits="userSpaceOnUse">
|
||||||
|
<path d="M 46 0 L 0 0 0 46" fill="none" stroke="rgba(35, 111, 135, 0.08)" stroke-width="1"/>
|
||||||
|
</pattern>
|
||||||
|
|
||||||
|
<!-- Button Gradient -->
|
||||||
|
<linearGradient id="buttonGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#236f87;stop-opacity:1" />
|
||||||
|
<stop offset="100%" style="stop-color:#1a5068;stop-opacity:1" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Icon Definitions -->
|
||||||
|
<g id="icon-link">
|
||||||
|
<path d="M 12 8 L 20 8 Q 22 8 22 10 L 22 16 Q 22 18 20 18 L 16 18 M 28 12 L 32 12 Q 34 12 34 14 L 34 20 Q 34 22 32 22 L 28 22 M 22 12 L 28 12"
|
||||||
|
stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g id="icon-users">
|
||||||
|
<circle cx="16" cy="10" r="3.5" fill="currentColor"/>
|
||||||
|
<path d="M 12 15 Q 12 13 16 13 Q 20 13 20 15 L 20 18 L 12 18 Z" fill="currentColor"/>
|
||||||
|
<circle cx="30" cy="10" r="3.5" fill="currentColor"/>
|
||||||
|
<path d="M 26 15 Q 26 13 30 13 Q 34 13 34 15 L 34 18 L 26 18 Z" fill="currentColor"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g id="icon-search">
|
||||||
|
<circle cx="18" cy="18" r="8" stroke="currentColor" stroke-width="2" fill="none"/>
|
||||||
|
<line x1="26" y1="26" x2="32" y2="32" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g id="icon-clipboard">
|
||||||
|
<rect x="12" y="8" width="16" height="24" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
||||||
|
<rect x="16" y="6" width="8" height="3" fill="currentColor"/>
|
||||||
|
<line x1="16" y1="14" x2="28" y2="14" stroke="currentColor" stroke-width="1.5"/>
|
||||||
|
<line x1="16" y1="18" x2="28" y2="18" stroke="currentColor" stroke-width="1.5"/>
|
||||||
|
<line x1="16" y1="22" x2="24" y2="22" stroke="currentColor" stroke-width="1.5"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Main Background -->
|
||||||
|
<rect class="bg-dark" width="800" height="500"/>
|
||||||
|
<rect class="bg-grid" width="800" height="500"/>
|
||||||
|
|
||||||
|
<!-- Dialog Container -->
|
||||||
|
<g class="shadow">
|
||||||
|
<rect class="bg-dark" x="60" y="40" width="680" height="420" rx="12" class="shadow"/>
|
||||||
|
<rect class="border-accent" x="60" y="40" width="680" height="420" rx="12"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Dialog Header -->
|
||||||
|
<g>
|
||||||
|
<text x="100" y="85" class="title-text">We are waiting...</text>
|
||||||
|
<g transform="translate(720, 60)">
|
||||||
|
<!-- Close Button -->
|
||||||
|
<circle cx="0" cy="0" r="16" stroke="rgba(35, 111, 135, 0.3)" stroke-width="1" fill="none"/>
|
||||||
|
<line x1="-6" y1="-6" x2="6" y2="6" stroke="rgba(149, 207, 245, 0.55)" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="6" y1="-6" x2="-6" y2="6" stroke="rgba(149, 207, 245, 0.55)" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Option 1: Invite a Friend -->
|
||||||
|
<g>
|
||||||
|
<!-- Option Container -->
|
||||||
|
<rect x="80" y="120" width="280" height="280" rx="8" fill="rgba(35, 111, 135, 0.05)" stroke="rgba(35, 111, 135, 0.15)" stroke-width="1"/>
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<g transform="translate(110, 145)">
|
||||||
|
<circle cx="0" cy="0" r="22" fill="rgba(35, 111, 135, 0.15)"/>
|
||||||
|
<g use="#icon-link" class="icon-color" transform="scale(1.8)"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<text x="160" y="165" class="header-text">Invite a Friend</text>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<text x="100" y="195" class="desc-text">Share this link with your opponent</text>
|
||||||
|
|
||||||
|
<!-- URL Box -->
|
||||||
|
<rect x="100" y="210" width="240" height="40" rx="6" fill="#d0e8f5" stroke="#7ab8d8" stroke-width="1"/>
|
||||||
|
<text x="118" y="237" style="font: 12px 'Courier New', monospace; fill: #1a4a6a; letter-spacing: 0.3px;">play.mineseeker.com/game-id</text>
|
||||||
|
|
||||||
|
<!-- Copy Button -->
|
||||||
|
<g class="glow">
|
||||||
|
<rect x="100" y="265" width="240" height="40" rx="5" class="button-gradient" stroke="#2e7a9a" stroke-width="1"/>
|
||||||
|
<g transform="translate(120, 285)">
|
||||||
|
<rect x="0" y="0" width="6" height="6" fill="#e0f4ff"/>
|
||||||
|
<rect x="2" y="2" width="4" height="4" fill="none" stroke="#e0f4ff" stroke-width="0.5"/>
|
||||||
|
</g>
|
||||||
|
<text x="140" y="287" class="button-text">Copy Link</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Divider OR -->
|
||||||
|
<g>
|
||||||
|
<line x1="400" y1="200" x2="400" y2="320" class="divider-line"/>
|
||||||
|
<circle cx="400" cy="260" r="18" fill="#07090d" stroke="rgba(35, 111, 135, 0.25)" stroke-width="1"/>
|
||||||
|
<text x="400" y="267" class="divider-text" text-anchor="middle">OR</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Option 2: Challenge a Player -->
|
||||||
|
<g>
|
||||||
|
<!-- Option Container -->
|
||||||
|
<rect x="440" y="120" width="280" height="280" rx="8" fill="rgba(35, 111, 135, 0.05)" stroke="rgba(35, 111, 135, 0.15)" stroke-width="1"/>
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<g transform="translate(470, 145)">
|
||||||
|
<circle cx="0" cy="0" r="22" fill="rgba(35, 111, 135, 0.15)"/>
|
||||||
|
<g use="#icon-users" class="icon-color" transform="scale(1.5)"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<text x="510" y="165" class="header-text">Challenge a Player</text>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<text x="460" y="195" class="desc-text">Browse online players and challenge</text>
|
||||||
|
|
||||||
|
<!-- Browse Button -->
|
||||||
|
<g class="glow">
|
||||||
|
<rect x="460" y="265" width="240" height="40" rx="5" class="button-gradient" stroke="#2e7a9a" stroke-width="1"/>
|
||||||
|
<g transform="translate(480, 285)">
|
||||||
|
<!-- Search icon simplified -->
|
||||||
|
<circle cx="4" cy="4" r="3" fill="none" stroke="#e0f4ff" stroke-width="1"/>
|
||||||
|
<line x1="7" y1="7" x2="9" y2="9" stroke="#e0f4ff" stroke-width="1" stroke-linecap="round"/>
|
||||||
|
</g>
|
||||||
|
<text x="510" y="287" class="button-text">Browse Players</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Highlight: Players Online -->
|
||||||
|
<g>
|
||||||
|
<text x="460" y="230" class="desc-text" style="font-weight: bold;">5 players waiting</text>
|
||||||
|
<g transform="translate(680, 220)">
|
||||||
|
<circle r="6" fill="#236f87"/>
|
||||||
|
<circle cx="-8" cy="3" r="4" fill="rgba(35, 111, 135, 0.6)"/>
|
||||||
|
<circle cx="8" cy="3" r="4" fill="rgba(35, 111, 135, 0.6)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Bottom Info -->
|
||||||
|
<g>
|
||||||
|
<text x="100" y="435" style="font: 11px 'Rajdhani', sans-serif; fill: rgba(149, 207, 245, 0.35); letter-spacing: 0.5px;">Choose either option to start playing or find an opponent</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 7.5 KiB |
21
assets/js/app.jsx
Normal file
21
assets/js/app.jsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import MineSeeker from './mine-seeker/MineSeeker';
|
||||||
|
|
||||||
|
const wrapper = document.getElementById('mine-wrapper');
|
||||||
|
|
||||||
|
createRoot(wrapper).render(
|
||||||
|
<MineSeeker
|
||||||
|
env={wrapper.dataset.env}
|
||||||
|
gameId={wrapper.dataset.gameId}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
71
assets/js/components/AvatarUpload.jsx
Normal file
71
assets/js/components/AvatarUpload.jsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
export default function AvatarUpload({ uploadUrl, initialThumbUrl, initials }) {
|
||||||
|
const [thumbUrl, setThumbUrl] = useState(initialThumbUrl || null);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
const inputRef = useRef(null);
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
inputRef.current?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChange(e) {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append('avatar', file);
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
fetch(uploadUrl, { method: 'POST', body: fd })
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
setError(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setThumbUrl(data.thumbUrl);
|
||||||
|
|
||||||
|
const navImg = document.querySelector('.hero-auth-avatar:not(.hero-auth-avatar--initials)');
|
||||||
|
const navInitials = document.querySelector('.hero-auth-avatar.hero-auth-avatar--initials');
|
||||||
|
if (navImg) {
|
||||||
|
navImg.src = data.thumbUrl;
|
||||||
|
} else if (navInitials) {
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = data.thumbUrl;
|
||||||
|
img.alt = navInitials.textContent.trim();
|
||||||
|
img.className = 'hero-auth-avatar';
|
||||||
|
navInitials.replaceWith(img);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => setError('Upload failed. Please try again.'))
|
||||||
|
.finally(() => setLoading(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`profile-avatar${loading ? ' profile-avatar--loading' : ''}`}
|
||||||
|
title="Click to change profile picture"
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{thumbUrl
|
||||||
|
? <img src={thumbUrl} alt={initials} className="profile-avatar__img" />
|
||||||
|
: <span className="profile-avatar__initials">{initials}</span>
|
||||||
|
}
|
||||||
|
<div className="profile-avatar__overlay">
|
||||||
|
<i className="fa fa-camera" />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
type="file"
|
||||||
|
accept="image/jpeg,image/png,image/gif,image/webp"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
{error && <div className="profile-avatar__error">{error}</div>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
238
assets/js/components/BattleDialog.jsx
Normal file
238
assets/js/components/BattleDialog.jsx
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import Dialog from '@mui/material/Dialog';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
|
|
||||||
|
const darkTheme = createTheme({ palette: { mode: 'dark' } });
|
||||||
|
|
||||||
|
const DIALOG_SX = {
|
||||||
|
'& .MuiDialog-paper': {
|
||||||
|
background: '#07090d',
|
||||||
|
backgroundImage: `
|
||||||
|
linear-gradient(rgba(35, 111, 135, 0.08) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(35, 111, 135, 0.08) 1px, transparent 1px)
|
||||||
|
`,
|
||||||
|
backgroundSize: '46px 46px',
|
||||||
|
border: '1px solid rgba(35, 111, 135, 0.4)',
|
||||||
|
borderRadius: '12px',
|
||||||
|
boxShadow: '0 0 80px rgba(35, 111, 135, 0.15), 0 32px 80px rgba(0,0,0,0.9)',
|
||||||
|
width: '580px',
|
||||||
|
maxWidth: '94vw',
|
||||||
|
overflow: 'hidden',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
'& .MuiBackdrop-root': {
|
||||||
|
background: 'rgba(2, 4, 8, 0.88)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const RESULT_META = {
|
||||||
|
win: {
|
||||||
|
label: 'Victory',
|
||||||
|
color: '#5ee89a',
|
||||||
|
bg: 'rgba(42,158,96,0.15)',
|
||||||
|
border: 'rgba(42,158,96,0.4)',
|
||||||
|
icon: 'fa-trophy',
|
||||||
|
},
|
||||||
|
loss: {
|
||||||
|
label: 'Defeat',
|
||||||
|
color: '#f67d52',
|
||||||
|
bg: 'rgba(173,10,5,0.15)',
|
||||||
|
border: 'rgba(173,10,5,0.4)',
|
||||||
|
icon: 'fa-flag',
|
||||||
|
},
|
||||||
|
draw: {
|
||||||
|
label: 'Draw',
|
||||||
|
color: '#95cff5',
|
||||||
|
bg: 'rgba(149,207,245,0.1)',
|
||||||
|
border: 'rgba(149,207,245,0.3)',
|
||||||
|
icon: 'fa-minus',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function Avatar({ name, color }) {
|
||||||
|
const isRed = 'red' === color;
|
||||||
|
const initials = (name || '?').slice(0, 2).toUpperCase();
|
||||||
|
|
||||||
|
const gradient = isRed
|
||||||
|
? 'linear-gradient(135deg, rgba(173,10,5,0.6) 0%, rgba(246,125,82,0.4) 100%)'
|
||||||
|
: 'linear-gradient(135deg, rgba(35,111,135,0.6) 0%, rgba(41,128,185,0.4) 100%)';
|
||||||
|
const glow = isRed
|
||||||
|
? '0 0 0 3px rgba(173,10,5,0.2), 0 0 28px rgba(173,10,5,0.35)'
|
||||||
|
: '0 0 0 3px rgba(35,111,135,0.2), 0 0 28px rgba(35,111,135,0.35)';
|
||||||
|
const border = isRed
|
||||||
|
? 'rgba(173,10,5,0.5)'
|
||||||
|
: 'rgba(35,111,135,0.5)';
|
||||||
|
const textColor = isRed ? '#f67d52' : '#95cff5';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10 }}>
|
||||||
|
<div style={{
|
||||||
|
width: 72, height: 72, borderRadius: '50%',
|
||||||
|
background: gradient,
|
||||||
|
border: `2px solid ${border}`,
|
||||||
|
boxShadow: glow,
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
font: '800 24px \'Rajdhani\', sans-serif',
|
||||||
|
color: textColor,
|
||||||
|
letterSpacing: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{initials}
|
||||||
|
</div>
|
||||||
|
<span style={{
|
||||||
|
font: '700 15px \'Rajdhani\', sans-serif',
|
||||||
|
color: textColor,
|
||||||
|
letterSpacing: 1,
|
||||||
|
maxWidth: 120, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||||
|
textAlign: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
<span style={{
|
||||||
|
font: '600 10px \'Rajdhani\', sans-serif',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: 2,
|
||||||
|
color: 'rgba(255,255,255,0.3)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isRed ? 'Red' : 'Blue'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function StatRow({ icon, label, value, valueColor }) {
|
||||||
|
return (
|
||||||
|
<div style={{
|
||||||
|
display: 'flex', alignItems: 'center',
|
||||||
|
gap: 10, padding: '9px 0',
|
||||||
|
borderBottom: '1px solid rgba(255,255,255,0.05)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className={`fa ${icon}`} style={{ width: 16, color: 'rgba(149,207,245,0.4)', fontSize: 13 }} />
|
||||||
|
<span style={{
|
||||||
|
font: '500 13px \'Rajdhani\', sans-serif',
|
||||||
|
color: 'rgba(255,255,255,0.45)',
|
||||||
|
flex: 1,
|
||||||
|
letterSpacing: 0.5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
<span style={{
|
||||||
|
font: '700 13px \'Rajdhani\', sans-serif',
|
||||||
|
color: valueColor || 'rgba(255,255,255,0.75)',
|
||||||
|
letterSpacing: 0.5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BattleDialog({ games }) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [game, setGame] = useState(null);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = e => {
|
||||||
|
const row = e.target.closest('[data-game-index]');
|
||||||
|
if (!row) return;
|
||||||
|
const idx = parseInt(row.dataset.gameIndex, 10);
|
||||||
|
if (!isNaN(idx) && games[idx]) {
|
||||||
|
setGame(games[idx]);
|
||||||
|
setOpen(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('click', handler);
|
||||||
|
return () => document.removeEventListener('click', handler);
|
||||||
|
}, [games]);
|
||||||
|
|
||||||
|
if (!game) {
|
||||||
|
return <ThemeProvider theme={darkTheme}><Dialog open={false} sx={DIALOG_SX} /></ThemeProvider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const meta = RESULT_META[game.result] ?? RESULT_META.draw;
|
||||||
|
const resign = game.resign;
|
||||||
|
const endReason = resign
|
||||||
|
? `${resign.charAt(0).toUpperCase() + resign.slice(1)} resigned`
|
||||||
|
: 'Points';
|
||||||
|
const shareUrl = `${window.location.origin}/battle/${game.id}`;
|
||||||
|
|
||||||
|
const handleShare = () => {
|
||||||
|
navigator.clipboard.writeText(shareUrl).then(() => {
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2200);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={darkTheme}>
|
||||||
|
<Dialog open={open} onClose={() => setOpen(false)} sx={DIALOG_SX}>
|
||||||
|
<div className="bd">
|
||||||
|
<div className="bd-header">
|
||||||
|
<div className="bd-header-left">
|
||||||
|
<span className="bd-label">Battle Report</span>
|
||||||
|
<h2 className="bd-title">
|
||||||
|
<i className="fa fa-crosshairs" /> Match Details
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', gap: 8 }}>
|
||||||
|
<button
|
||||||
|
className={`bd-share${copied ? ' bd-share--copied' : ''}`}
|
||||||
|
onClick={handleShare}
|
||||||
|
aria-label="Copy share link"
|
||||||
|
title="Copy share link"
|
||||||
|
>
|
||||||
|
<i className={`fa ${copied ? 'fa-check' : 'fa-share-alt'}`} />
|
||||||
|
{copied ? 'Copied!' : 'Share'}
|
||||||
|
</button>
|
||||||
|
<button className="bd-close" onClick={() => setOpen(false)} aria-label="Close">
|
||||||
|
<i className="fa fa-times" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="bd-vs-panel">
|
||||||
|
<Avatar name={game.redName} color="red" />
|
||||||
|
<div className="bd-vs-center">
|
||||||
|
<div className="bd-vs-score">
|
||||||
|
<span className="bd-vs-score__red">{game.redPoints ?? '—'}</span>
|
||||||
|
<span className="bd-vs-score__sep">:</span>
|
||||||
|
<span className="bd-vs-score__blue">{game.bluePoints ?? '—'}</span>
|
||||||
|
</div>
|
||||||
|
<div className="bd-vs-label">VS</div>
|
||||||
|
<div
|
||||||
|
className="bd-result-badge"
|
||||||
|
style={{ background: meta.bg, border: `1px solid ${meta.border}`, color: meta.color }}
|
||||||
|
>
|
||||||
|
<i className={`fa ${meta.icon}`} /> {meta.label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Avatar name={game.blueName} color="blue" />
|
||||||
|
</div>
|
||||||
|
<div className="bd-stats">
|
||||||
|
<StatRow icon="fa-calendar" label="Date" value={game.date ?? '—'} />
|
||||||
|
<StatRow icon="fa-flag-checkered" label="End reason" value={endReason} />
|
||||||
|
<StatRow
|
||||||
|
icon="fa-bomb" label="Red hit a mine"
|
||||||
|
value={game.redExplodedBomb ? 'Yes' : 'No'}
|
||||||
|
valueColor={game.redExplodedBomb ? '#f67d52' : 'rgba(255,255,255,0.45)'}
|
||||||
|
/>
|
||||||
|
<StatRow
|
||||||
|
icon="fa-bomb" label="Blue hit a mine"
|
||||||
|
value={game.blueExplodedBomb ? 'Yes' : 'No'}
|
||||||
|
valueColor={game.blueExplodedBomb ? '#f67d52' : 'rgba(255,255,255,0.45)'}
|
||||||
|
/>
|
||||||
|
{game.created && game.date && game.created !== game.date && (
|
||||||
|
<StatRow icon="fa-clock-o" label="Started" value={game.created} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
110
assets/js/components/PasskeyLogin.jsx
Normal file
110
assets/js/components/PasskeyLogin.jsx
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState, useCallback } from 'react';
|
||||||
|
|
||||||
|
const base64ToArrayBuffer = base64 => {
|
||||||
|
const binary = atob(base64.replace(/([-_])/g, m => ('-' === m ? '+' : '/')));
|
||||||
|
const bytes = new Uint8Array(binary.length);
|
||||||
|
for (let i = 0; i < binary.length; i++) {
|
||||||
|
bytes[i] = binary.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return bytes.buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
const arrayBufferToBase64url = buffer =>
|
||||||
|
btoa(String.fromCharCode(...new Uint8Array(buffer)))
|
||||||
|
.replace(/([+\/=])/g, m => ('+' === m ? '-' : '/' === m ? '_' : ''));
|
||||||
|
|
||||||
|
const credentialToJSON = credential => ({
|
||||||
|
id: credential.id,
|
||||||
|
rawId: arrayBufferToBase64url(credential.rawId),
|
||||||
|
type: credential.type,
|
||||||
|
response: {
|
||||||
|
authenticatorData: arrayBufferToBase64url(credential.response.authenticatorData),
|
||||||
|
clientDataJSON: arrayBufferToBase64url(credential.response.clientDataJSON),
|
||||||
|
signature: arrayBufferToBase64url(credential.response.signature),
|
||||||
|
userHandle: credential.response.userHandle
|
||||||
|
? arrayBufferToBase64url(credential.response.userHandle)
|
||||||
|
: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const PasskeyLogin = ({ apiRoutes }) => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const handleLogin = useCallback(async () => {
|
||||||
|
setLoading(true);
|
||||||
|
setError('');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const beginResponse = await fetch(apiRoutes.authenticationBegin, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!beginResponse.ok) throw new Error('Failed to get authentication options');
|
||||||
|
const options = await beginResponse.json();
|
||||||
|
|
||||||
|
const publicKey = {
|
||||||
|
...options,
|
||||||
|
challenge: base64ToArrayBuffer(options.challenge),
|
||||||
|
allowCredentials: (options.allowCredentials ?? []).map(cred => ({
|
||||||
|
...cred,
|
||||||
|
id: base64ToArrayBuffer(cred.id),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
const credential = await navigator.credentials.get({ publicKey });
|
||||||
|
if (!credential) throw new Error('Authentication was cancelled');
|
||||||
|
|
||||||
|
const completeResponse = await fetch(apiRoutes.authenticationComplete, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ credential: credentialToJSON(credential) }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!completeResponse.ok) {
|
||||||
|
const body = await completeResponse.json();
|
||||||
|
throw new Error(body.error || 'Authentication failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await completeResponse.json();
|
||||||
|
if (result.success) {
|
||||||
|
window.location.href = result.redirect || '/';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
}, [apiRoutes]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="auth-passkey-btn"
|
||||||
|
onClick={handleLogin}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<i className={loading ? 'fa fa-spinner fa-spin' : 'fa fa-key'} />
|
||||||
|
{loading ? 'Waiting for passkey…' : 'Sign In with Passkey'}
|
||||||
|
</button>
|
||||||
|
{error && (
|
||||||
|
<p className="auth-error" style={{ marginTop: '10px' }}>
|
||||||
|
<i className="fa fa-exclamation-triangle" /> {error}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PasskeyLogin;
|
||||||
410
assets/js/components/PasskeyManager.jsx
Normal file
410
assets/js/components/PasskeyManager.jsx
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Fragment, useCallback, useEffect, useState } from 'react';
|
||||||
|
import Dialog from '@mui/material/Dialog';
|
||||||
|
import DialogTitle from '@mui/material/DialogTitle';
|
||||||
|
import DialogContent from '@mui/material/DialogContent';
|
||||||
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
import TextField from '@mui/material/TextField';
|
||||||
|
|
||||||
|
const DIALOG_SX = {
|
||||||
|
'& .MuiDialog-paper': {
|
||||||
|
background: '#0a0e14',
|
||||||
|
color: '#e0e0e0',
|
||||||
|
},
|
||||||
|
'& .MuiTextField-root .MuiInputLabel-root': {
|
||||||
|
color: '#9e9e9e',
|
||||||
|
},
|
||||||
|
'& .MuiTextField-root .MuiOutlinedInput-root': {
|
||||||
|
'& fieldset': {
|
||||||
|
borderColor: 'rgba(35, 111, 135, 0.5)',
|
||||||
|
},
|
||||||
|
'&:hover fieldset': {
|
||||||
|
borderColor: 'rgba(35, 111, 135, 0.8)',
|
||||||
|
},
|
||||||
|
'&.Mui-focused fieldset': {
|
||||||
|
borderColor: '#236f87',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'& .MuiTextField-root .MuiOutlinedInput-input': {
|
||||||
|
color: '#e0e0e0',
|
||||||
|
},
|
||||||
|
'& .MuiFormHelperText-root': {
|
||||||
|
width: '500px',
|
||||||
|
maxWidth: '94vw',
|
||||||
|
overflow: 'hidden',
|
||||||
|
color: '#e0e0e0',
|
||||||
|
},
|
||||||
|
'& .MuiBackdrop-root': {
|
||||||
|
background: 'rgba(2, 4, 8, 0.88)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const base64ToArrayBuffer = base64 => {
|
||||||
|
const binary = atob(base64.replace(/([-_])/g, m => ('-' === m ? '+' : '/')));
|
||||||
|
const bytes = new Uint8Array(binary.length);
|
||||||
|
for (let i = 0; i < binary.length; i++) {
|
||||||
|
bytes[i] = binary.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return bytes.buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
const credentialToJSON = credential => {
|
||||||
|
const attestationObject = credential.response.attestationObject;
|
||||||
|
const clientDataJSON = credential.response.clientDataJSON;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: credential.id,
|
||||||
|
rawId: btoa(String.fromCharCode(...new Uint8Array(credential.rawId))).replace(/([+\/=])/g, m => ('+' === m ? '-' : '/' === m ? '_' : '')),
|
||||||
|
type: credential.type,
|
||||||
|
response: {
|
||||||
|
attestationObject: btoa(String.fromCharCode(...new Uint8Array(attestationObject))).replace(/([+\/=])/g, m => ('+' === m ? '-' : '/' === m ? '_' : '')),
|
||||||
|
clientDataJSON: btoa(String.fromCharCode(...new Uint8Array(clientDataJSON))).replace(/([+\/=])/g, m => ('+' === m ? '-' : '/' === m ? '_' : '')),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const PasskeyManager = ({ credentials, apiRoutes }) => {
|
||||||
|
const [addModalOpen, setAddModalOpen] = useState(false);
|
||||||
|
const [renameModalOpen, setRenameModalOpen] = useState(false);
|
||||||
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||||
|
const [selectedCredential, setSelectedCredential] = useState(null);
|
||||||
|
const [passkeyName, setPasskeyName] = useState('');
|
||||||
|
const [renameName, setRenameName] = useState('');
|
||||||
|
const [status, setStatus] = useState({ type: '', message: '' });
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [credentialsList, setCredentialsList] = useState(credentials);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCredentialsList(credentials);
|
||||||
|
}, [credentials]);
|
||||||
|
|
||||||
|
const showStatus = useCallback((message, type) => {
|
||||||
|
setStatus({ message, type });
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const closeAddModal = useCallback(() => {
|
||||||
|
setAddModalOpen(false);
|
||||||
|
setPasskeyName('');
|
||||||
|
setStatus({ type: '', message: '' });
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const openAddModal = useCallback(() => {
|
||||||
|
setPasskeyName('');
|
||||||
|
setStatus({ type: '', message: '' });
|
||||||
|
setAddModalOpen(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleAddPasskey = useCallback(async () => {
|
||||||
|
if (!passkeyName.trim()) {
|
||||||
|
showStatus('Please enter a passkey name', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
showStatus('Starting registration...', 'loading');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const optionsResponse = await fetch(apiRoutes.registrationBegin, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ credentialName: passkeyName.trim() }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!optionsResponse.ok) throw new Error('Failed to get registration options');
|
||||||
|
const options = await optionsResponse.json();
|
||||||
|
|
||||||
|
showStatus('Please touch your security key or use biometric authentication...', 'loading');
|
||||||
|
|
||||||
|
const publicKey = {
|
||||||
|
...options,
|
||||||
|
challenge: base64ToArrayBuffer(options.challenge),
|
||||||
|
user: {
|
||||||
|
...options.user,
|
||||||
|
id: base64ToArrayBuffer(options.user.id),
|
||||||
|
},
|
||||||
|
attestation: 'direct',
|
||||||
|
};
|
||||||
|
|
||||||
|
const credential = await navigator.credentials.create({ publicKey });
|
||||||
|
|
||||||
|
if (!credential) {
|
||||||
|
showStatus('Registration was cancelled', 'error');
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showStatus('Verifying credential...', 'loading');
|
||||||
|
|
||||||
|
const completeResponse = await fetch(apiRoutes.registrationComplete, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
credential: credentialToJSON(credential),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!completeResponse.ok) throw new Error('Failed to complete registration');
|
||||||
|
|
||||||
|
showStatus('Passkey registered successfully!', 'success');
|
||||||
|
setTimeout(() => window.location.reload(), 1500);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Registration error:', error);
|
||||||
|
showStatus('Error: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
}, [passkeyName, apiRoutes, showStatus]);
|
||||||
|
|
||||||
|
const openRenameModal = useCallback(credential => {
|
||||||
|
setSelectedCredential(credential);
|
||||||
|
setRenameName(credential.credentialName);
|
||||||
|
setStatus({ type: '', message: '' });
|
||||||
|
setRenameModalOpen(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const closeRenameModal = useCallback(() => {
|
||||||
|
setRenameModalOpen(false);
|
||||||
|
setSelectedCredential(null);
|
||||||
|
setRenameName('');
|
||||||
|
setStatus({ type: '', message: '' });
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleRename = useCallback(async () => {
|
||||||
|
if (!renameName.trim() || !selectedCredential) {
|
||||||
|
showStatus('Please enter a new name', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${apiRoutes.credentials}/${selectedCredential.id}/rename`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name: renameName.trim() }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to rename passkey');
|
||||||
|
|
||||||
|
window.location.reload();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Rename error:', error);
|
||||||
|
showStatus('Error: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
}, [renameName, selectedCredential, apiRoutes, showStatus]);
|
||||||
|
|
||||||
|
const openDeleteModal = useCallback(credential => {
|
||||||
|
setSelectedCredential(credential);
|
||||||
|
setDeleteModalOpen(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const closeDeleteModal = useCallback(() => {
|
||||||
|
setDeleteModalOpen(false);
|
||||||
|
setSelectedCredential(null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDelete = useCallback(async () => {
|
||||||
|
if (!selectedCredential) return;
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${apiRoutes.credentials}/${selectedCredential.id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
showStatus('Failed to delete passkey', 'error');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Delete error:', error);
|
||||||
|
showStatus('Error: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
setDeleteModalOpen(false);
|
||||||
|
}, [selectedCredential, apiRoutes, showStatus]);
|
||||||
|
|
||||||
|
const statusClass = 'error' === status.type
|
||||||
|
? 'registration-status--error'
|
||||||
|
: 'success' === status.type
|
||||||
|
? 'registration-status--success'
|
||||||
|
: 'loading' === status.type
|
||||||
|
? 'registration-status--loading'
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="passkey-manager">
|
||||||
|
<div className="passkey-manager__actions">
|
||||||
|
<button className="btn btn--primary" onClick={openAddModal} type="button">
|
||||||
|
<i className="fa fa-plus" /> Add Passkey
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="passkey-manager__list">
|
||||||
|
{0 < credentialsList.length ? (
|
||||||
|
credentialsList.map(credential => (
|
||||||
|
<div key={credential.id} className="passkey-item" data-credential-id={credential.id}>
|
||||||
|
<div className="passkey-item__header">
|
||||||
|
<div className="passkey-item__info">
|
||||||
|
<h3 className="passkey-item__name">{credential.credentialName}</h3>
|
||||||
|
<p className="passkey-item__meta">
|
||||||
|
Created: {credential.createdAt}
|
||||||
|
{credential.lastUsedAt && (
|
||||||
|
<>
|
||||||
|
<br />Last used: {credential.lastUsedAt}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="passkey-item__badges">
|
||||||
|
{credential.isBackupEligible && (
|
||||||
|
<span className="badge badge--info" title="This passkey can be backed up">
|
||||||
|
<i className="fa fa-cloud" /> Backup Eligible
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{credential.isBackupAuthenticated && (
|
||||||
|
<span className="badge badge--success" title="This passkey is backed up">
|
||||||
|
<i className="fa fa-check" /> Backed Up
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="passkey-item__actions">
|
||||||
|
<button
|
||||||
|
className="btn btn--sm btn--warning"
|
||||||
|
onClick={() => openRenameModal(credential)}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<i className="fa fa-edit" /> Rename
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn--sm btn--danger"
|
||||||
|
onClick={() => openDeleteModal(credential)}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<i className="fa fa-trash" /> Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="empty-state">
|
||||||
|
<i className="fa fa-key empty-state__icon" />
|
||||||
|
<p className="empty-state__text">No passkeys registered yet.</p>
|
||||||
|
<p className="empty-state__subtext">
|
||||||
|
Add your first passkey to get started with secure, passwordless authentication.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Dialog open={addModalOpen} onClose={closeAddModal} sx={DIALOG_SX}>
|
||||||
|
<DialogTitle>Add New Passkey</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
fullWidth
|
||||||
|
id="passkeyName"
|
||||||
|
label="Passkey Name"
|
||||||
|
placeholder="e.g., My Laptop, iPhone"
|
||||||
|
value={passkeyName}
|
||||||
|
onChange={e => setPasskeyName(e.target.value)}
|
||||||
|
onKeyUp={e => 'Enter' === e.key && handleAddPasskey()}
|
||||||
|
margin="dense"
|
||||||
|
variant="outlined"
|
||||||
|
helperText="Give this passkey a descriptive name to help you remember it."
|
||||||
|
/>
|
||||||
|
{status.message && (
|
||||||
|
<div className={`registration-status ${statusClass}`}>
|
||||||
|
{status.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={closeAddModal} disabled={loading}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleAddPasskey} variant="contained" disabled={loading}>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Dialog open={renameModalOpen} onClose={closeRenameModal} sx={DIALOG_SX}>
|
||||||
|
<DialogTitle>Rename Passkey</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
fullWidth
|
||||||
|
id="renamePasskeyName"
|
||||||
|
label="New Name"
|
||||||
|
value={renameName}
|
||||||
|
onChange={e => setRenameName(e.target.value)}
|
||||||
|
onKeyUp={e => 'Enter' === e.key && handleRename()}
|
||||||
|
margin="dense"
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
{status.message && (
|
||||||
|
<div className={`registration-status ${statusClass}`}>
|
||||||
|
{status.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={closeRenameModal} disabled={loading}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleRename} variant="contained" disabled={loading}>
|
||||||
|
Rename
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Dialog open={deleteModalOpen} onClose={closeDeleteModal} sx={DIALOG_SX}>
|
||||||
|
<DialogTitle>Delete Passkey</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<p>
|
||||||
|
Are you sure you want to delete the passkey
|
||||||
|
{selectedCredential && (
|
||||||
|
<Fragment>
|
||||||
|
<strong>{selectedCredential.credentialName}</strong>?
|
||||||
|
This action cannot be undone.
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
{status.message && (
|
||||||
|
<div className={`registration-status ${statusClass}`}>
|
||||||
|
{status.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={closeDeleteModal} disabled={loading}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleDelete} variant="contained" color="error" disabled={loading}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PasskeyManager;
|
||||||
103
assets/js/components/ProfileCharts.jsx
Normal file
103
assets/js/components/ProfileCharts.jsx
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { BarChart } from '@mui/x-charts/BarChart';
|
||||||
|
import { PieChart } from '@mui/x-charts/PieChart';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
|
|
||||||
|
const darkTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: 'dark',
|
||||||
|
background: { paper: 'transparent' },
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
fontFamily: '\'Rajdhani\', sans-serif',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const WIN_COLOR = '#5ee89a';
|
||||||
|
const LOSS_COLOR = '#f67d52';
|
||||||
|
const DRAW_COLOR = '#95cff5';
|
||||||
|
|
||||||
|
const axisStyle = {
|
||||||
|
tickLabelStyle: { fill: 'rgba(255,255,255,0.4)', fontSize: 11, fontFamily: '\'Rajdhani\', sans-serif' },
|
||||||
|
labelStyle: { fill: 'rgba(255,255,255,0.4)', fontSize: 11, fontFamily: '\'Rajdhani\', sans-serif' },
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ProfileCharts({ chartData }) {
|
||||||
|
const { months, wins, losses, draws, pieWins, pieLosses, pieDraws } = chartData;
|
||||||
|
const total = pieWins + pieLosses + pieDraws;
|
||||||
|
|
||||||
|
const hasBars = wins.some(v => 0 < v) || losses.some(v => 0 < v) || draws.some(v => 0 < v);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={darkTheme}>
|
||||||
|
<div className="profile-charts">
|
||||||
|
{0 < total && (
|
||||||
|
<div className="profile-chart-block">
|
||||||
|
<h2 className="profile-section__title">
|
||||||
|
<i className="fa fa-pie-chart" /> Result Breakdown
|
||||||
|
</h2>
|
||||||
|
<div className="profile-chart-inner">
|
||||||
|
<PieChart
|
||||||
|
series={[{
|
||||||
|
data: [
|
||||||
|
{ id: 0, value: pieWins, label: `Wins ${pieWins}`, color: WIN_COLOR },
|
||||||
|
{ id: 1, value: pieLosses, label: `Losses ${pieLosses}`, color: LOSS_COLOR },
|
||||||
|
{ id: 2, value: pieDraws, label: `Draws ${pieDraws}`, color: DRAW_COLOR },
|
||||||
|
],
|
||||||
|
innerRadius: 52,
|
||||||
|
paddingAngle: 3,
|
||||||
|
cornerRadius: 4,
|
||||||
|
highlightScope: { fade: 'global', highlight: 'item' },
|
||||||
|
}]}
|
||||||
|
slotProps={{
|
||||||
|
legend: {
|
||||||
|
labelStyle: {
|
||||||
|
fill: 'rgba(255,255,255,0.55)',
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: '\'Rajdhani\', sans-serif',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
width={320}
|
||||||
|
height={200}
|
||||||
|
margin={{ top: 10, bottom: 10, left: 10, right: 120 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasBars && (
|
||||||
|
<div className="profile-chart-block">
|
||||||
|
<h2 className="profile-section__title">
|
||||||
|
<i className="fa fa-bar-chart" /> Activity (6 months)
|
||||||
|
</h2>
|
||||||
|
<div className="profile-chart-inner">
|
||||||
|
<BarChart
|
||||||
|
xAxis={[{ scaleType: 'band', data: months, ...axisStyle }]}
|
||||||
|
yAxis={[{ ...axisStyle }]}
|
||||||
|
series={[
|
||||||
|
{ data: wins, label: 'Wins', color: WIN_COLOR, stack: 'total' },
|
||||||
|
{ data: losses, label: 'Losses', color: LOSS_COLOR, stack: 'total' },
|
||||||
|
{ data: draws, label: 'Draws', color: DRAW_COLOR, stack: 'total' },
|
||||||
|
]}
|
||||||
|
slotProps={{
|
||||||
|
legend: {
|
||||||
|
labelStyle: {
|
||||||
|
fill: 'rgba(255,255,255,0.55)',
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: '\'Rajdhani\', sans-serif',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
borderRadius={3}
|
||||||
|
width={460}
|
||||||
|
height={200}
|
||||||
|
margin={{ top: 10, bottom: 30, left: 30, right: 120 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
35
assets/js/mine-seeker/MineSeeker.jsx
Normal file
35
assets/js/mine-seeker/MineSeeker.jsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { GameProvider } from '@mine-contexts';
|
||||||
|
import { GameBoard } from '@mine-components';
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
const MineSeeker = ({ env, gameId }) => {
|
||||||
|
const isEnvDev = 'dev' === env;
|
||||||
|
const gameAssoc = useRef('' !== gameId ? gameId : crypto.randomUUID()).current;
|
||||||
|
const gameInherited = '' !== gameId;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<GameProvider>
|
||||||
|
<GameBoard
|
||||||
|
gameAssoc={gameAssoc}
|
||||||
|
gameInherited={gameInherited}
|
||||||
|
isEnvDev={isEnvDev}
|
||||||
|
/>
|
||||||
|
</GameProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MineSeeker;
|
||||||
33
assets/js/mine-seeker/components/GameBoard.jsx
Normal file
33
assets/js/mine-seeker/components/GameBoard.jsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { useGame } from '@mine-contexts';
|
||||||
|
import { useServerCommunication } from '@mine-hooks';
|
||||||
|
import GridControl from './grid/GridControl';
|
||||||
|
|
||||||
|
export const GameBoard = ({ gameAssoc, gameInherited, isEnvDev }) => {
|
||||||
|
const { gridReady } = useGame();
|
||||||
|
const { onClick, resign } = useServerCommunication(gameAssoc, gameInherited, isEnvDev);
|
||||||
|
|
||||||
|
if (!gridReady) {
|
||||||
|
return (
|
||||||
|
<div className="game-overlay">
|
||||||
|
<div className="game-overlay-window"><h1>Loading…</h1></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GridControl
|
||||||
|
onClick={onClick}
|
||||||
|
resign={resign}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
179
assets/js/mine-seeker/components/GameTimer.jsx
Normal file
179
assets/js/mine-seeker/components/GameTimer.jsx
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import { useGame } from '@mine-contexts';
|
||||||
|
|
||||||
|
const renderAvatar = player => {
|
||||||
|
if (!player.registered) return null;
|
||||||
|
return (
|
||||||
|
<div className="timer-avatar">
|
||||||
|
{player.avatar
|
||||||
|
? <img src={player.avatar} alt={player.name} className="timer-avatar__img" />
|
||||||
|
: <span className="timer-avatar__initials">{player.name.slice(0, 2).toUpperCase()}</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GameTimer = () => {
|
||||||
|
const { overlay, connectionLost, endRef, activePlayer, red, blue } = useGame();
|
||||||
|
const [redTime, setRedTime] = useState(0);
|
||||||
|
const [blueTime, setBlueTime] = useState(0);
|
||||||
|
const [isRunning, setIsRunning] = useState(false);
|
||||||
|
const timerIntervalRef = useRef(null);
|
||||||
|
const gameStartedRef = useRef(false);
|
||||||
|
|
||||||
|
// Use timestamps instead of counters for more reliable background tracking
|
||||||
|
const redStartTimeRef = useRef(null);
|
||||||
|
const blueStartTimeRef = useRef(null);
|
||||||
|
const lastActivePlayerRef = useRef(null);
|
||||||
|
const pausedRedTimeRef = useRef(0);
|
||||||
|
const pausedBlueTimeRef = useRef(0);
|
||||||
|
|
||||||
|
// Start timer when overlay is hidden (both players connected and game started)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!overlay && !gameStartedRef.current) {
|
||||||
|
gameStartedRef.current = true;
|
||||||
|
setIsRunning(true);
|
||||||
|
setRedTime(0);
|
||||||
|
setBlueTime(0);
|
||||||
|
redStartTimeRef.current = Date.now();
|
||||||
|
blueStartTimeRef.current = Date.now();
|
||||||
|
pausedRedTimeRef.current = 0;
|
||||||
|
pausedBlueTimeRef.current = 0;
|
||||||
|
lastActivePlayerRef.current = activePlayer;
|
||||||
|
}
|
||||||
|
}, [overlay]);
|
||||||
|
|
||||||
|
// Stop timer on game end (resign/win)
|
||||||
|
useEffect(() => {
|
||||||
|
if (endRef.current) {
|
||||||
|
setIsRunning(false);
|
||||||
|
}
|
||||||
|
}, [endRef.current]);
|
||||||
|
|
||||||
|
// Stop timer on connection loss
|
||||||
|
useEffect(() => {
|
||||||
|
if (connectionLost) {
|
||||||
|
setIsRunning(false);
|
||||||
|
}
|
||||||
|
}, [connectionLost]);
|
||||||
|
|
||||||
|
// Handle player switch - pause one timer, resume the other
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isRunning) return;
|
||||||
|
|
||||||
|
if (lastActivePlayerRef.current !== activePlayer) {
|
||||||
|
// Player switched, save current accumulated time for whoever was active
|
||||||
|
const startRef = lastActivePlayerRef.current ? blueStartTimeRef.current : redStartTimeRef.current;
|
||||||
|
if (startRef) {
|
||||||
|
const elapsed = Math.floor((Date.now() - startRef) / 1000);
|
||||||
|
if (lastActivePlayerRef.current) {
|
||||||
|
pausedBlueTimeRef.current += elapsed;
|
||||||
|
} else {
|
||||||
|
pausedRedTimeRef.current += elapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the new active player's timer
|
||||||
|
if (activePlayer) {
|
||||||
|
blueStartTimeRef.current = Date.now();
|
||||||
|
} else {
|
||||||
|
redStartTimeRef.current = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
lastActivePlayerRef.current = activePlayer;
|
||||||
|
}
|
||||||
|
}, [activePlayer, isRunning]);
|
||||||
|
|
||||||
|
// Main timer effect - update display every 100ms
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isRunning) {
|
||||||
|
if (timerIntervalRef.current) {
|
||||||
|
clearInterval(timerIntervalRef.current);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timerIntervalRef.current = setInterval(() => {
|
||||||
|
let currentRedTime = pausedRedTimeRef.current;
|
||||||
|
let currentBlueTime = pausedBlueTimeRef.current;
|
||||||
|
|
||||||
|
// Add elapsed time for the active player
|
||||||
|
if (!activePlayer && redStartTimeRef.current) {
|
||||||
|
currentRedTime += Math.floor((Date.now() - redStartTimeRef.current) / 1000);
|
||||||
|
} else if (activePlayer && blueStartTimeRef.current) {
|
||||||
|
currentBlueTime += Math.floor((Date.now() - blueStartTimeRef.current) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
setRedTime(currentRedTime);
|
||||||
|
setBlueTime(currentBlueTime);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (timerIntervalRef.current) {
|
||||||
|
clearInterval(timerIntervalRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [isRunning, activePlayer]);
|
||||||
|
|
||||||
|
// Handle focus/blur to synchronize timer when tab regains focus
|
||||||
|
useEffect(() => {
|
||||||
|
const handleFocus = () => {
|
||||||
|
// Force update when tab regains focus to sync any background drift
|
||||||
|
if (isRunning) {
|
||||||
|
let currentRedTime = pausedRedTimeRef.current;
|
||||||
|
let currentBlueTime = pausedBlueTimeRef.current;
|
||||||
|
|
||||||
|
if (!activePlayer && redStartTimeRef.current) {
|
||||||
|
currentRedTime += Math.floor((Date.now() - redStartTimeRef.current) / 1000);
|
||||||
|
} else if (activePlayer && blueStartTimeRef.current) {
|
||||||
|
currentBlueTime += Math.floor((Date.now() - blueStartTimeRef.current) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
setRedTime(currentRedTime);
|
||||||
|
setBlueTime(currentBlueTime);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('focus', handleFocus);
|
||||||
|
return () => window.removeEventListener('focus', handleFocus);
|
||||||
|
}, [isRunning, activePlayer]);
|
||||||
|
|
||||||
|
// Cleanup on unmount
|
||||||
|
useEffect(() => () => {
|
||||||
|
if (timerIntervalRef.current) {
|
||||||
|
clearInterval(timerIntervalRef.current);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const formatTime = seconds => {
|
||||||
|
const mins = Math.floor(seconds / 60);
|
||||||
|
const secs = seconds % 60;
|
||||||
|
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="game-timer-container">
|
||||||
|
<div className={`game-timer red-timer ${!activePlayer ? 'active' : ''}`}>
|
||||||
|
{renderAvatar(red)}
|
||||||
|
<i className={`fa ${!activePlayer ? 'fa-hourglass-half' : 'fa-hourglass-start'} timer-icon`} />
|
||||||
|
<span className="timer-display">{formatTime(redTime)}</span>
|
||||||
|
</div>
|
||||||
|
<div className={`game-timer blue-timer ${activePlayer ? 'active' : ''}`}>
|
||||||
|
{renderAvatar(blue)}
|
||||||
|
<i className={`fa ${activePlayer ? 'fa-hourglass-half' : 'fa-hourglass-start'} timer-icon`} />
|
||||||
|
<span className="timer-display">{formatTime(blueTime)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GameTimer;
|
||||||
252
assets/js/mine-seeker/components/OnlinePlayersDialog.jsx
Normal file
252
assets/js/mine-seeker/components/OnlinePlayersDialog.jsx
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import Dialog from '@mui/material/Dialog';
|
||||||
|
|
||||||
|
const DIALOG_SX = {
|
||||||
|
'& .MuiDialog-paper': {
|
||||||
|
background: '#07090d',
|
||||||
|
backgroundImage: `
|
||||||
|
linear-gradient(rgba(35, 111, 135, 0.08) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(35, 111, 135, 0.08) 1px, transparent 1px)
|
||||||
|
`,
|
||||||
|
backgroundSize: '46px 46px',
|
||||||
|
border: '1px solid rgba(35, 111, 135, 0.4)',
|
||||||
|
borderRadius: '12px',
|
||||||
|
boxShadow: '0 0 80px rgba(35, 111, 135, 0.15), 0 32px 80px rgba(0, 0, 0, 0.9)',
|
||||||
|
width: '500px',
|
||||||
|
maxWidth: '94vw',
|
||||||
|
overflow: 'hidden',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
'& .MuiBackdrop-root': {
|
||||||
|
background: 'rgba(2, 4, 8, 0.88)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatSince = isoStr => {
|
||||||
|
const diff = Math.floor((Date.now() - new Date(isoStr)) / 60000);
|
||||||
|
if (1 > diff) return 'just now';
|
||||||
|
if (1 === diff) return '1 min ago';
|
||||||
|
return `${diff} min ago`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OnlinePlayersDialog = ({ open, onClose, currentGameAssoc }) => {
|
||||||
|
const [players, setPlayers] = useState([]);
|
||||||
|
const [search, setSearch] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [refreshKey, setRefreshKey] = useState(0);
|
||||||
|
const [snapshotLoaded, setSnapshotLoaded] = useState(false);
|
||||||
|
const [challengingGameAssoc, setChallengingGameAssoc] = useState(null);
|
||||||
|
const [declinedMsg, setDeclinedMsg] = useState('');
|
||||||
|
const declinedTimerRef = useRef(null);
|
||||||
|
|
||||||
|
const addPlayer = useCallback(entry => {
|
||||||
|
setPlayers(prev =>
|
||||||
|
prev.some(p => p.gameAssoc === entry.gameAssoc)
|
||||||
|
? prev
|
||||||
|
: [...prev, entry],
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const removePlayer = useCallback(gameAssoc => {
|
||||||
|
setPlayers(prev => prev.filter(p => p.gameAssoc !== gameAssoc));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
setLoading(true);
|
||||||
|
setSnapshotLoaded(false);
|
||||||
|
fetch('/api/game/waiting')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
// Filter out current user's game from the snapshot
|
||||||
|
const filtered = data.filter(p => p.gameAssoc !== currentGameAssoc);
|
||||||
|
setPlayers(filtered);
|
||||||
|
setSnapshotLoaded(true);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setPlayers([]);
|
||||||
|
setSnapshotLoaded(true);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}, [open, refreshKey, currentGameAssoc]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open || !snapshotLoaded) return;
|
||||||
|
setSearch('');
|
||||||
|
|
||||||
|
const wrapper = document.getElementById('mine-wrapper');
|
||||||
|
const hubUrl = wrapper?.dataset?.mercureHubUrl;
|
||||||
|
const jwt = wrapper?.dataset?.mercureSubscriberJwt;
|
||||||
|
if (!hubUrl) return;
|
||||||
|
|
||||||
|
const url = new URL(hubUrl, window.location.origin);
|
||||||
|
url.searchParams.append('topic', 'mineseeker/lobby');
|
||||||
|
if (jwt) url.searchParams.append('authorization', jwt);
|
||||||
|
|
||||||
|
const es = new EventSource(url.toString());
|
||||||
|
es.onmessage = e => {
|
||||||
|
const { action, gameAssoc, name, since } = JSON.parse(e.data);
|
||||||
|
// Don't add the current user's game to the list
|
||||||
|
if (gameAssoc === currentGameAssoc) return;
|
||||||
|
if ('join' === action) addPlayer({ gameAssoc, name, since });
|
||||||
|
if ('leave' === action) removePlayer(gameAssoc);
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => es.close();
|
||||||
|
}, [open, snapshotLoaded, addPlayer, removePlayer, currentGameAssoc]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = () => {
|
||||||
|
setChallengingGameAssoc(null);
|
||||||
|
clearTimeout(declinedTimerRef.current);
|
||||||
|
setDeclinedMsg('Challenge was not accepted.');
|
||||||
|
declinedTimerRef.current = setTimeout(() => setDeclinedMsg(''), 3500);
|
||||||
|
};
|
||||||
|
window.addEventListener('challenge-declined', handler);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('challenge-declined', handler);
|
||||||
|
clearTimeout(declinedTimerRef.current);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleChallenge = player => {
|
||||||
|
if (challengingGameAssoc) return;
|
||||||
|
setChallengingGameAssoc(player.gameAssoc);
|
||||||
|
setDeclinedMsg('');
|
||||||
|
fetch('/api/game/challenge/' + player.gameAssoc, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ challengerGameAssoc: currentGameAssoc }),
|
||||||
|
}).catch(() => setChallengingGameAssoc(null));
|
||||||
|
};
|
||||||
|
|
||||||
|
const visible = players
|
||||||
|
.filter(p => p.gameAssoc !== currentGameAssoc)
|
||||||
|
.filter(p => p.name.toLowerCase().includes(search.toLowerCase()));
|
||||||
|
|
||||||
|
const shown = visible.slice(0, 5);
|
||||||
|
const hasMore = 5 < visible.length;
|
||||||
|
|
||||||
|
// Debug: log if currentGameAssoc is undefined or if current user appears
|
||||||
|
if ('development' === process.env.NODE_ENV && 0 < players.length) {
|
||||||
|
const userInList = players.find(p => p.gameAssoc === currentGameAssoc);
|
||||||
|
if (userInList) {
|
||||||
|
console.warn('[OnlinePlayersDialog] Current user appears in players list:', { currentGameAssoc, userInList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={onClose} sx={DIALOG_SX}>
|
||||||
|
<div className="opd">
|
||||||
|
<div className="opd-header">
|
||||||
|
<div className="opd-header-text">
|
||||||
|
<span className="opd-label">Multiplayer</span>
|
||||||
|
<h2 className="opd-title">
|
||||||
|
<i className="fa fa-users" />
|
||||||
|
Online Players
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="opd-header-actions">
|
||||||
|
<button
|
||||||
|
className={`opd-refresh${loading ? ' opd-refresh--spin' : ''}`}
|
||||||
|
onClick={() => setRefreshKey(k => k + 1)}
|
||||||
|
disabled={loading}
|
||||||
|
aria-label="Refresh"
|
||||||
|
title="Refresh list"
|
||||||
|
>
|
||||||
|
<i className="fa fa-refresh" />
|
||||||
|
</button>
|
||||||
|
<button className="opd-close" onClick={onClose} aria-label="Close">
|
||||||
|
<i className="fa fa-times" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="opd-search-wrap">
|
||||||
|
<i className="fa fa-search opd-search-icon" />
|
||||||
|
<input
|
||||||
|
className="opd-search"
|
||||||
|
placeholder="Search by username…"
|
||||||
|
value={search}
|
||||||
|
onChange={e => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
|
{search && (
|
||||||
|
<button className="opd-search-clear" onClick={() => setSearch('')}>
|
||||||
|
<i className="fa fa-times" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="opd-list">
|
||||||
|
{loading && (
|
||||||
|
<div className="opd-empty">
|
||||||
|
<i className="fa fa-spinner fa-spin" />
|
||||||
|
<p>Loading players…</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && 0 === shown.length && (
|
||||||
|
<div className="opd-empty">
|
||||||
|
<i className="fa fa-hourglass-half" />
|
||||||
|
<p>
|
||||||
|
{search
|
||||||
|
? 'No players match your search.'
|
||||||
|
: 'No other players are waiting right now.'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{declinedMsg && (
|
||||||
|
<div className="opd-declined">
|
||||||
|
<i className="fa fa-times-circle" />
|
||||||
|
{' '}{declinedMsg}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && shown.map(player => {
|
||||||
|
const isWaiting = challengingGameAssoc === player.gameAssoc;
|
||||||
|
return (
|
||||||
|
<div key={player.gameAssoc} className="opd-row">
|
||||||
|
<div className="opd-avatar">
|
||||||
|
{player.name.slice(0, 2).toUpperCase()}
|
||||||
|
</div>
|
||||||
|
<div className="opd-info">
|
||||||
|
<span className="opd-name">{player.name}</span>
|
||||||
|
<span className="opd-since">
|
||||||
|
<i className="fa fa-clock-o" />
|
||||||
|
{' '}Waiting {formatSince(player.since)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className={`opd-join${isWaiting ? ' opd-join--waiting' : ''}`}
|
||||||
|
onClick={() => handleChallenge(player)}
|
||||||
|
disabled={!!challengingGameAssoc}
|
||||||
|
>
|
||||||
|
<i className={`fa ${isWaiting ? 'fa-spinner fa-spin' : 'fa-play'}`} />
|
||||||
|
{isWaiting ? 'Waiting...' : 'Join'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!loading && hasMore && (
|
||||||
|
<p className="opd-note">
|
||||||
|
Showing 5 of {visible.length} waiting players
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OnlinePlayersDialog;
|
||||||
85
assets/js/mine-seeker/components/WaitingOverlayContent.jsx
Normal file
85
assets/js/mine-seeker/components/WaitingOverlayContent.jsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
import { Fragment, useState } from 'react';
|
||||||
|
import { OnlinePlayersDialog } from '@mine-components';
|
||||||
|
|
||||||
|
const WaitingOverlayContent = ({ shareUrl, currentGameAssoc }) => {
|
||||||
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className="waiting-options">
|
||||||
|
<div className="waiting-option">
|
||||||
|
<div className="waiting-option-header">
|
||||||
|
<i className="fa fa-link" />
|
||||||
|
<span>Invite a Friend</span>
|
||||||
|
</div>
|
||||||
|
<p className="waiting-option-desc">Share this link with your opponent</p>
|
||||||
|
<ShareLinkBox
|
||||||
|
url={shareUrl}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="waiting-divider">
|
||||||
|
<span>OR</span>
|
||||||
|
</div>
|
||||||
|
<div className="waiting-option">
|
||||||
|
<div className="waiting-option-header">
|
||||||
|
<i className="fa fa-users" />
|
||||||
|
<span>Challenge a Player</span>
|
||||||
|
</div>
|
||||||
|
<p className="waiting-option-desc">Browse online players and challenge them</p>
|
||||||
|
<button
|
||||||
|
className="browse-players-btn"
|
||||||
|
onClick={() => setDialogOpen(true)}
|
||||||
|
>
|
||||||
|
<i className="fa fa-search" />
|
||||||
|
Browse Players
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<OnlinePlayersDialog
|
||||||
|
open={dialogOpen}
|
||||||
|
onClose={() => setDialogOpen(false)}
|
||||||
|
currentGameAssoc={currentGameAssoc}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ShareLinkBox = ({ url }) => {
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
navigator.clipboard.writeText(url).then(() => {
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2500);
|
||||||
|
}).catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="share-invite">
|
||||||
|
<div className="share-url-box" onClick={e => e.currentTarget.querySelector('input').select()}>
|
||||||
|
<i className="fa fa-link share-url-icon" />
|
||||||
|
<input
|
||||||
|
className="share-url-input"
|
||||||
|
readOnly
|
||||||
|
value={url}
|
||||||
|
onClick={e => e.target.select()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button className={`share-copy-btn${copied ? ' copied' : ''}`} onClick={handleCopy}>
|
||||||
|
<i className={`fa ${copied ? 'fa-check' : 'fa-clipboard'}`} />
|
||||||
|
{copied ? 'Copied!' : 'Copy Link'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WaitingOverlayContent;
|
||||||
75
assets/js/mine-seeker/components/grid/GridControl.jsx
Normal file
75
assets/js/mine-seeker/components/grid/GridControl.jsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import { useGame } from '@mine-contexts';
|
||||||
|
import GridField from './GridField';
|
||||||
|
import UserControl from '../user/UserControl';
|
||||||
|
import GameTimer from '../GameTimer';
|
||||||
|
import { BOMB_SYMBOLS, bombRadius } from '@mine-utils';
|
||||||
|
|
||||||
|
const GridControl = ({ onClick, resign }) => {
|
||||||
|
const {
|
||||||
|
overlay, overlayTitle, overlaySubTitle,
|
||||||
|
webPlayer, activePlayer, bombSelected,
|
||||||
|
cells, setCells,
|
||||||
|
} = useGame();
|
||||||
|
|
||||||
|
const handleHover = (row, col) => {
|
||||||
|
if (!bombSelected) return;
|
||||||
|
const activeColor = activePlayer ? 'blue' : 'red';
|
||||||
|
if (activeColor !== webPlayer) return;
|
||||||
|
|
||||||
|
setCells(prev => {
|
||||||
|
const next = prev.map(r => r.map(c =>
|
||||||
|
null !== c.bombTargetArea ? { ...c, bombTargetArea: null } : c,
|
||||||
|
));
|
||||||
|
bombRadius(row, col, prev.length, prev[0]?.length ?? 0).forEach(([r, c], i) => {
|
||||||
|
if (!next[r]?.[c]) return;
|
||||||
|
|
||||||
|
next[r] = [...next[r]];
|
||||||
|
next[r][c] = { ...next[r][c], bombTargetArea: BOMB_SYMBOLS[i] };
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<GameTimer />
|
||||||
|
<div className="game-wrapper">
|
||||||
|
<div className={`game-overlay${overlay ? '' : ' hide'}`}>
|
||||||
|
<div className="game-overlay-window">
|
||||||
|
<h1>{overlayTitle}</h1>
|
||||||
|
<h2>{overlaySubTitle}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<UserControl
|
||||||
|
resign={resign}
|
||||||
|
/>
|
||||||
|
<div className="grid-container">
|
||||||
|
<div className="grid">
|
||||||
|
{cells.flatMap((row, r) =>
|
||||||
|
row.map((cell, c) => (
|
||||||
|
<GridField
|
||||||
|
key={`${r}_${c}`}
|
||||||
|
cell={cell}
|
||||||
|
onClick={() => onClick([r, c])}
|
||||||
|
onMouseEnter={() => handleHover(r, c)}
|
||||||
|
/>
|
||||||
|
)),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GridControl;
|
||||||
74
assets/js/mine-seeker/components/grid/GridField.jsx
Normal file
74
assets/js/mine-seeker/components/grid/GridField.jsx
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { memo, useMemo } from 'react';
|
||||||
|
import { IMAGES } from '@mine-utils';
|
||||||
|
|
||||||
|
const bombSrc = area => {
|
||||||
|
if (null === area) return null;
|
||||||
|
const vert = ['left', 'center', 'right'][area[0]] ?? null;
|
||||||
|
const hor = ['top', 'middle', 'bottom'][area[1]] ?? null;
|
||||||
|
if (null === vert || null === hor) return IMAGES.bombEmpty;
|
||||||
|
return IMAGES.bombPos(hor, vert);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GridField = memo(function GridField({ cell, onClick, onMouseEnter }) {
|
||||||
|
const { currentImage, currentObj, active, lastClickedRed, lastClickedBlue, bombTargetArea } = cell;
|
||||||
|
|
||||||
|
const fieldClass = 'field'
|
||||||
|
+ (active ? ' active' : '')
|
||||||
|
+ (active && 'm' === currentObj ? ' mine' : '')
|
||||||
|
+ ' color-' + currentObj;
|
||||||
|
const bombSourceString = useMemo(() => bombSrc(bombTargetArea), [bombTargetArea]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="field-wrapper"
|
||||||
|
onClick={onClick}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="field-target"
|
||||||
|
src={IMAGES.target}
|
||||||
|
alt="Field of target"
|
||||||
|
/>
|
||||||
|
{bombSourceString && (
|
||||||
|
<img
|
||||||
|
className="field-bomb-target"
|
||||||
|
src={bombSourceString}
|
||||||
|
alt="Field of bomb target"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{(lastClickedRed || lastClickedBlue) && (
|
||||||
|
<img
|
||||||
|
className={`field-${lastClickedRed ? 'red' : 'blue'}-last last-clicked`}
|
||||||
|
src={IMAGES.last(lastClickedRed ? 'red' : 'blue')}
|
||||||
|
alt="Last clicked area"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className={fieldClass}>
|
||||||
|
<div className="field-corner">
|
||||||
|
{isNaN(currentImage) && (
|
||||||
|
<div className="flag-mine">
|
||||||
|
<img src={currentImage} alt="" />
|
||||||
|
<div className="flag-mine-base" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isNaN(currentImage) && 0 !== currentImage && (
|
||||||
|
<div className="flag-number">
|
||||||
|
{currentImage}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default GridField;
|
||||||
17
assets/js/mine-seeker/components/index.js
Normal file
17
assets/js/mine-seeker/components/index.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { GameBoard } from './GameBoard';
|
||||||
|
export { default as OnlinePlayersDialog } from './OnlinePlayersDialog';
|
||||||
|
export { default as WaitingOverlayContent } from './WaitingOverlayContent';
|
||||||
|
export { default as GameTimer } from './GameTimer';
|
||||||
|
export { default as GridControl } from './grid/GridControl';
|
||||||
|
export { default as GridField } from './grid/GridField';
|
||||||
|
export { default as User } from './user/User';
|
||||||
|
export { default as UserControl } from './user/UserControl';
|
||||||
54
assets/js/mine-seeker/components/user/User.jsx
Normal file
54
assets/js/mine-seeker/components/user/User.jsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { memo } from 'react';
|
||||||
|
import { IMAGES } from '@mine-utils';
|
||||||
|
|
||||||
|
const User = memo(function User(
|
||||||
|
{
|
||||||
|
color,
|
||||||
|
webPlayer,
|
||||||
|
name,
|
||||||
|
desc,
|
||||||
|
active,
|
||||||
|
mines,
|
||||||
|
haveBomb,
|
||||||
|
enabledBomb,
|
||||||
|
onClickBombSelector,
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const buzzClass = 'bomb-container'
|
||||||
|
+ (active && color === webPlayer && haveBomb && enabledBomb ? ' buzz' : '');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`user-container user-${color}`}>
|
||||||
|
<div className="user-header">
|
||||||
|
<div className="user-color">{color}</div>
|
||||||
|
{active && <img src={IMAGES.cursor(color)} alt="" className="user-cursor" />}
|
||||||
|
<img src={IMAGES.figure(color)} alt="" />
|
||||||
|
</div>
|
||||||
|
<div className="user-name"> {name} </div>
|
||||||
|
<div className="user-caret"><i className="fa fa-caret-down" /></div>
|
||||||
|
<div className="user-desc"> {desc} </div>
|
||||||
|
<div className="user-control">
|
||||||
|
<img src={IMAGES.flag(color)} alt="" />
|
||||||
|
<div className="user-control-mines">{mines}</div>
|
||||||
|
<div className={buzzClass} onClick={onClickBombSelector}>
|
||||||
|
<div className="bomb">
|
||||||
|
{haveBomb && <img src={enabledBomb && active ? IMAGES.bomb : IMAGES.bombDisabled} alt="" />}
|
||||||
|
{!haveBomb && <img src={IMAGES.bombExploded} alt="" />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="clear" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default User;
|
||||||
54
assets/js/mine-seeker/components/user/UserControl.jsx
Normal file
54
assets/js/mine-seeker/components/user/UserControl.jsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { useGame } from '@mine-contexts';
|
||||||
|
import User from './User';
|
||||||
|
|
||||||
|
const UserControl = ({ resign }) => {
|
||||||
|
const { webPlayer, activePlayer, mines, foundMines, red, blue, onBombToggle } = useGame();
|
||||||
|
const activeColor = activePlayer ? 'blue' : 'red';
|
||||||
|
const resignClass = 'resign' + (activeColor !== webPlayer ? ' disabled' : '');
|
||||||
|
const minesClass = 'active-mines' + (foundMines ? ' found-mine' : '');
|
||||||
|
|
||||||
|
const handleBombClick = (color, player) => {
|
||||||
|
const p = 'red' === color ? red : blue;
|
||||||
|
if (p.haveBomb && p.enabledBomb && activePlayer === player) {
|
||||||
|
onBombToggle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="users">
|
||||||
|
<User
|
||||||
|
color="blue" webPlayer={webPlayer} {...blue}
|
||||||
|
onClickBombSelector={() => handleBombClick('blue', 1)}
|
||||||
|
/>
|
||||||
|
<div className="active-mines-container">
|
||||||
|
<i className="fa fa-star" />
|
||||||
|
<div className={minesClass}>
|
||||||
|
<div className="active-mines-nbr">{mines}</div>
|
||||||
|
<div className="active-mines-shine" />
|
||||||
|
</div>
|
||||||
|
<i className="fa fa-star" />
|
||||||
|
</div>
|
||||||
|
<div className="clear" />
|
||||||
|
<User
|
||||||
|
color="red" webPlayer={webPlayer} {...red}
|
||||||
|
onClickBombSelector={() => handleBombClick('red', 0)}
|
||||||
|
/>
|
||||||
|
<button className={resignClass} onClick={resign}>
|
||||||
|
<div className="resign-shine" />
|
||||||
|
Resign
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserControl;
|
||||||
16
assets/js/mine-seeker/contexts/GameContext.jsx
Normal file
16
assets/js/mine-seeker/contexts/GameContext.jsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
|
const GameContext = createContext(null);
|
||||||
|
|
||||||
|
export const useGame = () => useContext(GameContext);
|
||||||
|
|
||||||
|
export default GameContext;
|
||||||
246
assets/js/mine-seeker/contexts/GameProvider.jsx
Normal file
246
assets/js/mine-seeker/contexts/GameProvider.jsx
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { Howl } from 'howler';
|
||||||
|
import GameContext from './GameContext';
|
||||||
|
import { useGameRefs, useGameState } from '@mine-hooks';
|
||||||
|
import { DESC, IMAGES, patchCells } from '@mine-utils';
|
||||||
|
|
||||||
|
export const GameProvider = ({ children }) => {
|
||||||
|
const {
|
||||||
|
webPlayerRef,
|
||||||
|
activePlayerRef,
|
||||||
|
bombSelectedRef,
|
||||||
|
connectionLostRef,
|
||||||
|
redRef,
|
||||||
|
blueRef,
|
||||||
|
lastClickedRef,
|
||||||
|
endRef,
|
||||||
|
} = useGameRefs();
|
||||||
|
|
||||||
|
const {
|
||||||
|
webPlayer, setWebPlayer,
|
||||||
|
activePlayer, setActivePlayer,
|
||||||
|
overlay, setOverlay,
|
||||||
|
overlayTitle, setOverlayTitle,
|
||||||
|
overlaySubTitle, setOverlaySubTitle,
|
||||||
|
mines, setMines,
|
||||||
|
bombSelected, setBombSelected,
|
||||||
|
foundMines, setFoundMines,
|
||||||
|
red, setRed,
|
||||||
|
blue, setBlue,
|
||||||
|
cells, setCells,
|
||||||
|
gridReady, setGridReady,
|
||||||
|
connectionLost, setConnectionLost,
|
||||||
|
} = useGameState();
|
||||||
|
|
||||||
|
const sounds = useRef({
|
||||||
|
click: new Howl({ src: ['/sound/click.mp3'] }),
|
||||||
|
bomb: new Howl({ src: ['/sound/bomb.mp3'] }),
|
||||||
|
mine: new Howl({ src: ['/sound/mine.mp3'] }),
|
||||||
|
warning: new Howl({ src: ['/sound/warning.mp3'] }),
|
||||||
|
won: new Howl({ src: ['/sound/won.mp3'] }),
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Sync helpers (keep ref + state in lockstep) */
|
||||||
|
|
||||||
|
const syncWebPlayer = v => {
|
||||||
|
webPlayerRef.current = v;
|
||||||
|
setWebPlayer(v);
|
||||||
|
};
|
||||||
|
const syncActivePlayer = v => {
|
||||||
|
activePlayerRef.current = v;
|
||||||
|
setActivePlayer(v);
|
||||||
|
};
|
||||||
|
const syncBombSelected = v => {
|
||||||
|
bombSelectedRef.current = v;
|
||||||
|
setBombSelected(v);
|
||||||
|
};
|
||||||
|
const syncConnLost = v => {
|
||||||
|
connectionLostRef.current = v;
|
||||||
|
setConnectionLost(v);
|
||||||
|
};
|
||||||
|
const syncRed = fn => {
|
||||||
|
const n = fn(redRef.current);
|
||||||
|
redRef.current = n;
|
||||||
|
setRed(n);
|
||||||
|
};
|
||||||
|
const syncBlue = fn => {
|
||||||
|
const n = fn(blueRef.current);
|
||||||
|
blueRef.current = n;
|
||||||
|
setBlue(n);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Overlay */
|
||||||
|
|
||||||
|
const showOverlay = (title, sub) => {
|
||||||
|
setOverlay(true);
|
||||||
|
setOverlayTitle(title);
|
||||||
|
setOverlaySubTitle(sub);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideOverlay = () => setOverlay(false);
|
||||||
|
|
||||||
|
/** Cell helpers */
|
||||||
|
|
||||||
|
const applyRevealedCell = (cell, player, isMainCell = false) => {
|
||||||
|
const { row, col, value } = cell;
|
||||||
|
setCells(prev => {
|
||||||
|
if (prev[row][col].active) return prev;
|
||||||
|
const patch = 'm' === value
|
||||||
|
? { currentImage: IMAGES.flag(player), currentObj: 'm', active: true }
|
||||||
|
: { currentImage: value, currentObj: value, active: true };
|
||||||
|
if (isMainCell) {
|
||||||
|
patch.lastClickedRed = 'red' === player;
|
||||||
|
patch.lastClickedBlue = 'blue' === player;
|
||||||
|
}
|
||||||
|
return patchCells(prev, [{ row, col, ...patch }]);
|
||||||
|
});
|
||||||
|
if (isMainCell) lastClickedRef.current = { ...lastClickedRef.current, [player]: [row, col] };
|
||||||
|
};
|
||||||
|
|
||||||
|
const showLeftMines = (leftMines = []) => {
|
||||||
|
if (!leftMines.length) return;
|
||||||
|
setCells(prev => {
|
||||||
|
const patches = leftMines
|
||||||
|
.filter(({ row, col }) => !prev[row][col].active)
|
||||||
|
.map(({ row, col }) => ({ row, col, currentImage: IMAGES.leftMine }));
|
||||||
|
return patches.length ? patchCells(prev, patches) : prev;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Game logic */
|
||||||
|
|
||||||
|
const changePlayer = () => {
|
||||||
|
const wasColor = activePlayerRef.current ? 'blue' : 'red';
|
||||||
|
const nextColor = activePlayerRef.current ? 'red' : 'blue';
|
||||||
|
const nextVal = activePlayerRef.current ? 0 : 1;
|
||||||
|
const desc = wasColor === webPlayerRef.current ? DESC.buddy : DESC.you;
|
||||||
|
|
||||||
|
syncActivePlayer(nextVal);
|
||||||
|
syncRed(p => ({ ...p, active: 'red' === nextColor, desc: 'red' === nextColor ? desc : '' }));
|
||||||
|
syncBlue(p => ({ ...p, active: 'blue' === nextColor, desc: 'blue' === nextColor ? desc : '' }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyStep = stepData => {
|
||||||
|
const { player, bomb: isBomb, minesFound = 0, revealedCells = [], redPoints: rp, bluePoints: bp } = stepData;
|
||||||
|
|
||||||
|
if (isBomb) {
|
||||||
|
sounds.current.bomb.play();
|
||||||
|
} else if (0 < minesFound) {
|
||||||
|
const cur = ('red' === player ? redRef : blueRef).current.mines;
|
||||||
|
sounds.current[20 < cur + minesFound ? 'warning' : 'mine'].play();
|
||||||
|
} else {
|
||||||
|
sounds.current.click.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
const lc = lastClickedRef.current[player];
|
||||||
|
setCells(prev => {
|
||||||
|
let next = prev;
|
||||||
|
if (lc) next = patchCells(next, [{ row: lc[0], col: lc[1], lastClickedRed: false, lastClickedBlue: false }]);
|
||||||
|
|
||||||
|
revealedCells.forEach(({ row, col, value }, idx) => {
|
||||||
|
if (next[row][col].active) return;
|
||||||
|
const patch = 'm' === value
|
||||||
|
? { currentImage: IMAGES.flag(player), currentObj: 'm', active: true }
|
||||||
|
: { currentImage: value, currentObj: value, active: true };
|
||||||
|
if (0 === idx) {
|
||||||
|
patch.lastClickedRed = 'red' === player;
|
||||||
|
patch.lastClickedBlue = 'blue' === player;
|
||||||
|
}
|
||||||
|
next = patchCells(next, [{ row, col, ...patch }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isBomb) next = next.map(r => r.map(c => null !== c.bombTargetArea ? { ...c, bombTargetArea: null } : c));
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (0 < revealedCells.length) {
|
||||||
|
lastClickedRef.current = { ...lastClickedRef.current, [player]: [revealedCells[0].row, revealedCells[0].col] };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 < minesFound) {
|
||||||
|
setMines(51 - rp - bp);
|
||||||
|
setFoundMines(true);
|
||||||
|
setTimeout(() => setFoundMines(false), 500);
|
||||||
|
syncRed(p => ({ ...p, mines: 'red' === player ? rp : p.mines }));
|
||||||
|
syncBlue(p => ({ ...p, mines: 'blue' === player ? bp : p.mines }));
|
||||||
|
}
|
||||||
|
|
||||||
|
syncRed(p => ({ ...p, enabledBomb: rp <= bp }));
|
||||||
|
syncBlue(p => ({ ...p, enabledBomb: bp <= rp }));
|
||||||
|
|
||||||
|
if (isBomb || 0 === minesFound) changePlayer();
|
||||||
|
|
||||||
|
if (isBomb) {
|
||||||
|
syncBombSelected(false);
|
||||||
|
syncRed(p => 'red' === player ? { ...p, haveBomb: false } : p);
|
||||||
|
syncBlue(p => 'blue' === player ? { ...p, haveBomb: false } : p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeGameEndIfItEnds = (bluePoints, redPoints, resign = false, leftMines = []) => {
|
||||||
|
const redWins = 25 < redPoints;
|
||||||
|
const blueWins = 25 < bluePoints;
|
||||||
|
|
||||||
|
if (redWins || blueWins || resign) {
|
||||||
|
sounds.current.won.play();
|
||||||
|
|
||||||
|
if (!resign) showOverlay((redWins ? 'Red' : 'Blue') + ' wins the game!', 'Play again!');
|
||||||
|
|
||||||
|
showLeftMines(leftMines);
|
||||||
|
syncActivePlayer(false);
|
||||||
|
syncRed(p => ({ ...p, desc: '' }));
|
||||||
|
syncBlue(p => ({ ...p, desc: '' }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resignProcess = color => {
|
||||||
|
const wp = webPlayerRef.current;
|
||||||
|
showOverlay(
|
||||||
|
color === wp ? 'You have been give up' : 'Your opponent has been resigned',
|
||||||
|
color === wp ? 'You LOSE!' : 'You WIN!',
|
||||||
|
);
|
||||||
|
endRef.current = true;
|
||||||
|
makeGameEndIfItEnds(0, 0, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBombToggle = () => {
|
||||||
|
const next = !bombSelectedRef.current;
|
||||||
|
syncBombSelected(next);
|
||||||
|
if (!next) {
|
||||||
|
setCells(prev => prev.map(r => r.map(c => null !== c.bombTargetArea ? { ...c, bombTargetArea: null } : c)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GameContext.Provider
|
||||||
|
value={{
|
||||||
|
// State (for rendering)
|
||||||
|
webPlayer, activePlayer, overlay, overlayTitle, overlaySubTitle,
|
||||||
|
mines, bombSelected, foundMines, red, blue, cells, gridReady, connectionLost,
|
||||||
|
// Setters needed by useServerComm
|
||||||
|
setCells, setGridReady,
|
||||||
|
// Refs (needed by useServerComm for async-safe reads)
|
||||||
|
webPlayerRef, activePlayerRef, bombSelectedRef, connectionLostRef, endRef,
|
||||||
|
// Sync helpers
|
||||||
|
syncWebPlayer, syncActivePlayer, syncBombSelected, syncConnLost, syncRed, syncBlue,
|
||||||
|
// Game logic called by useServerComm
|
||||||
|
showOverlay, hideOverlay,
|
||||||
|
applyRevealedCell, applyStep,
|
||||||
|
makeGameEndIfItEnds, resignProcess,
|
||||||
|
// UI action
|
||||||
|
onBombToggle,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</GameContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
13
assets/js/mine-seeker/contexts/index.js
Normal file
13
assets/js/mine-seeker/contexts/index.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { useGame } from './GameContext';
|
||||||
|
export { GameProvider } from './GameProvider';
|
||||||
|
export { default as GameContext } from './GameContext';
|
||||||
|
|
||||||
14
assets/js/mine-seeker/hooks/index.js
Normal file
14
assets/js/mine-seeker/hooks/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { default as useGameRefs } from './useGameRefs';
|
||||||
|
export { default as useGameState } from './useGameState';
|
||||||
|
export { default as useServerCommunication } from './useServerCommunication';
|
||||||
|
export { default as useStepTimer } from './useStepTimer';
|
||||||
|
|
||||||
35
assets/js/mine-seeker/hooks/useGameRefs.jsx
Normal file
35
assets/js/mine-seeker/hooks/useGameRefs.jsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useRef } from 'react';
|
||||||
|
import { PLAYER_DEF } from '@mine-utils';
|
||||||
|
|
||||||
|
const useGameRefs = () => {
|
||||||
|
const webPlayerRef = useRef(null);
|
||||||
|
const activePlayerRef = useRef(false);
|
||||||
|
const bombSelectedRef = useRef(false);
|
||||||
|
const connectionLostRef = useRef(false);
|
||||||
|
const redRef = useRef({ ...PLAYER_DEF });
|
||||||
|
const blueRef = useRef({ ...PLAYER_DEF });
|
||||||
|
const lastClickedRef = useRef({ red: null, blue: null });
|
||||||
|
const endRef = useRef(false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
webPlayerRef,
|
||||||
|
activePlayerRef,
|
||||||
|
bombSelectedRef,
|
||||||
|
connectionLostRef,
|
||||||
|
redRef,
|
||||||
|
blueRef,
|
||||||
|
lastClickedRef,
|
||||||
|
endRef,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGameRefs;
|
||||||
45
assets/js/mine-seeker/hooks/useGameState.jsx
Normal file
45
assets/js/mine-seeker/hooks/useGameState.jsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { initCells, PLAYER_DEF } from '@mine-utils';
|
||||||
|
|
||||||
|
const useGameState = () => {
|
||||||
|
const [webPlayer, setWebPlayer] = useState(null);
|
||||||
|
const [activePlayer, setActivePlayer] = useState(false);
|
||||||
|
const [overlay, setOverlay] = useState(true);
|
||||||
|
const [overlayTitle, setOverlayTitle] = useState('');
|
||||||
|
const [overlaySubTitle, setOverlaySubTitle] = useState('');
|
||||||
|
const [mines, setMines] = useState(51);
|
||||||
|
const [bombSelected, setBombSelected] = useState(false);
|
||||||
|
const [foundMines, setFoundMines] = useState(false);
|
||||||
|
const [red, setRed] = useState({ ...PLAYER_DEF });
|
||||||
|
const [blue, setBlue] = useState({ ...PLAYER_DEF });
|
||||||
|
const [cells, setCells] = useState(initCells);
|
||||||
|
const [gridReady, setGridReady] = useState(false);
|
||||||
|
const [connectionLost, setConnectionLost] = useState(false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
webPlayer, setWebPlayer,
|
||||||
|
activePlayer, setActivePlayer,
|
||||||
|
overlay, setOverlay,
|
||||||
|
overlayTitle, setOverlayTitle,
|
||||||
|
overlaySubTitle, setOverlaySubTitle,
|
||||||
|
mines, setMines,
|
||||||
|
bombSelected, setBombSelected,
|
||||||
|
foundMines, setFoundMines,
|
||||||
|
red, setRed,
|
||||||
|
blue, setBlue,
|
||||||
|
cells, setCells,
|
||||||
|
gridReady, setGridReady,
|
||||||
|
connectionLost, setConnectionLost,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGameState;
|
||||||
342
assets/js/mine-seeker/hooks/useServerCommunication.jsx
Normal file
342
assets/js/mine-seeker/hooks/useServerCommunication.jsx
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
|
import { useGame } from '@mine-contexts';
|
||||||
|
import { DESC } from '@mine-utils';
|
||||||
|
import useStepTimer from './useStepTimer';
|
||||||
|
import { WaitingOverlayContent } from '@mine-components';
|
||||||
|
|
||||||
|
/** Handles all server communication: SSE (Mercure), REST calls, and the initialization lifecycle. */
|
||||||
|
const useServerCommunication = (gameAssoc, gameInherited, isEnvDev) => {
|
||||||
|
const {
|
||||||
|
/** Async-safe refs */
|
||||||
|
webPlayerRef, activePlayerRef, bombSelectedRef, connectionLostRef, endRef,
|
||||||
|
/** State setters */
|
||||||
|
setGridReady,
|
||||||
|
/** Sync helpers */
|
||||||
|
syncWebPlayer, syncActivePlayer, syncBombSelected, syncConnLost, syncRed, syncBlue,
|
||||||
|
/** Game logic */
|
||||||
|
showOverlay, hideOverlay,
|
||||||
|
applyRevealedCell, applyStep,
|
||||||
|
makeGameEndIfItEnds, resignProcess,
|
||||||
|
/** Current cells snapshot (for active-check in onClick) */
|
||||||
|
cells,
|
||||||
|
} = useGame();
|
||||||
|
|
||||||
|
const eventSourceRef = useRef(null);
|
||||||
|
const rpcUsersRef = useRef(null);
|
||||||
|
const stepCacheRef = useRef([]);
|
||||||
|
const { getStepElapsed, resetStepTimer, startNewTurn } = useStepTimer();
|
||||||
|
const isGameRunningRef = useRef(false);
|
||||||
|
const lastActivePlayerRef = useRef(null);
|
||||||
|
|
||||||
|
/** REST mutations / queries */
|
||||||
|
|
||||||
|
const connectQuery = useQuery({
|
||||||
|
queryKey: ['game-connect', gameAssoc],
|
||||||
|
queryFn: () => fetch('/api/game/connect/' + gameAssoc)
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(b64 => JSON.parse(window.atob(b64))),
|
||||||
|
enabled: false,
|
||||||
|
retry: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const startMutation = useMutation({
|
||||||
|
mutationFn: () => fetch('/api/game/start', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ gameAssoc }),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const joinMutation = useMutation({
|
||||||
|
mutationFn: () => fetch('/api/game/join/' + gameAssoc, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
}).catch(e => isEnvDev && console.error('Join error', e)),
|
||||||
|
});
|
||||||
|
|
||||||
|
const stepMutation = useMutation({
|
||||||
|
mutationFn: dataPack => fetch('/api/game/step/' + gameAssoc, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(dataPack),
|
||||||
|
}).then(r => r.json()),
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Game-start helpers (triggered by server events) */
|
||||||
|
|
||||||
|
const wInit = (revealedCells = []) => {
|
||||||
|
setGridReady(true);
|
||||||
|
showOverlay('Choose an opponent!', gameAssoc ? (
|
||||||
|
<WaitingOverlayContent
|
||||||
|
shareUrl={`${window.location.href}/${gameAssoc}`}
|
||||||
|
currentGameAssoc={gameAssoc}
|
||||||
|
/>
|
||||||
|
) : '');
|
||||||
|
setTimeout(() => revealedCells.forEach(cell => applyRevealedCell(cell, cell.player)), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeGameStart = payload => {
|
||||||
|
syncActivePlayer(1);
|
||||||
|
syncRed(p => ({
|
||||||
|
...p,
|
||||||
|
name: payload.users.red || payload.users.redAnon || p.name,
|
||||||
|
registered: !!payload.users.red,
|
||||||
|
avatar: payload.users.redAvatar ?? null,
|
||||||
|
}));
|
||||||
|
syncBlue(p => ({
|
||||||
|
...p,
|
||||||
|
name: payload.users.blue || payload.users.blueAnon || p.name,
|
||||||
|
registered: !!payload.users.blue,
|
||||||
|
avatar: payload.users.blueAvatar ?? null,
|
||||||
|
desc: 'blue' === webPlayerRef.current ? DESC.you : DESC.buddy,
|
||||||
|
active: true,
|
||||||
|
}));
|
||||||
|
isGameRunningRef.current = true;
|
||||||
|
lastActivePlayerRef.current = 1; // Blue starts
|
||||||
|
startNewTurn();
|
||||||
|
resetStepTimer();
|
||||||
|
hideOverlay();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Mercure / SSE message handlers */
|
||||||
|
|
||||||
|
const wSubscribe = (payload, rpcUsers = null) => {
|
||||||
|
isEnvDev && console.info((payload.user ?? 'user') + ' subscribed');
|
||||||
|
const firstUser = !rpcUsers;
|
||||||
|
|
||||||
|
if (null === webPlayerRef.current) {
|
||||||
|
const isBlue = payload.user === payload.users.blue
|
||||||
|
|| (firstUser ? '' !== payload.users.blueAnon : '' === rpcUsers.blueAnon && '' === rpcUsers.blue);
|
||||||
|
syncWebPlayer(isBlue ? 'blue' : 'red');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
2 === payload.userCnt
|
||||||
|
&& (!connectionLostRef.current
|
||||||
|
|| (connectionLostRef.current && false === activePlayerRef.current && !endRef.current))
|
||||||
|
) {
|
||||||
|
makeGameStart(payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const wUnsubscribe = payload => {
|
||||||
|
isEnvDev && console.info(payload.msg);
|
||||||
|
showOverlay('The connection has been lost w/ your friend...', 'Please, restart the game!');
|
||||||
|
};
|
||||||
|
|
||||||
|
const wChallenge = payload => {
|
||||||
|
const { challengerName, challengerGameAssoc } = payload;
|
||||||
|
|
||||||
|
const handleAccept = () => {
|
||||||
|
fetch('/api/game/challenge/respond/' + challengerGameAssoc, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ accepted: true, targetGameAssoc: gameAssoc }),
|
||||||
|
}).then(() => {
|
||||||
|
showOverlay('Challenge accepted!', 'Waiting for the challenger to join...');
|
||||||
|
}).catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDecline = () => {
|
||||||
|
fetch('/api/game/challenge/respond/' + challengerGameAssoc, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ accepted: false, targetGameAssoc: gameAssoc }),
|
||||||
|
}).then(() => {
|
||||||
|
showOverlay('We are waiting for your opponent...', gameAssoc ? (
|
||||||
|
<WaitingOverlayContent
|
||||||
|
shareUrl={window.location.origin + '/play/' + gameAssoc}
|
||||||
|
currentGameAssoc={gameAssoc}
|
||||||
|
/>
|
||||||
|
) : '');
|
||||||
|
}).catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
showOverlay(
|
||||||
|
challengerName + ' wants to challenge you!',
|
||||||
|
<div className="resign">
|
||||||
|
<a onClick={handleAccept}>Accept</a>
|
||||||
|
<a onClick={handleDecline}>Decline</a>
|
||||||
|
</div>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const wChallengeResponse = payload => {
|
||||||
|
if (payload.accepted) {
|
||||||
|
window.location.href = '/play/' + payload.targetGameAssoc;
|
||||||
|
} else {
|
||||||
|
window.dispatchEvent(new CustomEvent('challenge-declined'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const wTopic = payload => {
|
||||||
|
if (webPlayerRef.current !== payload.data.player) {
|
||||||
|
if (null === payload.data.resign) {
|
||||||
|
isEnvDev && console.warn(payload.user + ' stepped to ' + payload.data.coords.join(','));
|
||||||
|
syncBombSelected(payload.data.bomb);
|
||||||
|
|
||||||
|
// Detect if turn switched (other player made a move)
|
||||||
|
// After their move, it's now our turn (or the opposite player's turn)
|
||||||
|
if (lastActivePlayerRef.current !== activePlayerRef.current) {
|
||||||
|
startNewTurn();
|
||||||
|
lastActivePlayerRef.current = activePlayerRef.current;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyStep(payload.data);
|
||||||
|
makeGameEndIfItEnds(payload.data.bluePoints, payload.data.redPoints, false, payload.data.leftMines);
|
||||||
|
} else {
|
||||||
|
resignProcess(payload.data.resign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMercureMessage = payload => {
|
||||||
|
if (undefined !== payload.type) {
|
||||||
|
if ('challenge' === payload.type) wChallenge(payload);
|
||||||
|
else if ('challenge-response' === payload.type) wChallengeResponse(payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (undefined !== payload.data) {
|
||||||
|
wTopic(payload);
|
||||||
|
} else if (undefined === payload.msg) {
|
||||||
|
wSubscribe(payload, rpcUsersRef.current);
|
||||||
|
} else {
|
||||||
|
wUnsubscribe(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 === payload.userCnt && connectionLostRef.current) {
|
||||||
|
isEnvDev && console.info('Reconnection');
|
||||||
|
stepCacheRef.current.forEach(item => stepMutation.mutate(item));
|
||||||
|
stepCacheRef.current = [];
|
||||||
|
syncConnLost(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const openEventSource = () => {
|
||||||
|
const wrapper = document.getElementById('mine-wrapper');
|
||||||
|
const hubUrl = wrapper.dataset.mercureHubUrl;
|
||||||
|
const subscriberJwt = wrapper.dataset.mercureSubscriberJwt;
|
||||||
|
const url = new URL(hubUrl, window.location.origin);
|
||||||
|
|
||||||
|
url.searchParams.append('topic', 'mineseeker/channel/' + gameAssoc);
|
||||||
|
if (subscriberJwt) url.searchParams.append('authorization', subscriberJwt);
|
||||||
|
|
||||||
|
if (eventSourceRef.current) eventSourceRef.current.close();
|
||||||
|
|
||||||
|
const es = new EventSource(url.toString());
|
||||||
|
es.onmessage = e => handleMercureMessage(JSON.parse(e.data));
|
||||||
|
es.onopen = () => {
|
||||||
|
isEnvDev && console.info('SSE opened');
|
||||||
|
if (connectionLostRef.current) {
|
||||||
|
isEnvDev && console.info('SSE reconnected');
|
||||||
|
joinMutation.mutate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
es.onerror = () => {
|
||||||
|
isEnvDev && console.error('SSE error');
|
||||||
|
syncConnLost(true);
|
||||||
|
};
|
||||||
|
eventSourceRef.current = es;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Initialization */
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (connectionLostRef.current) {
|
||||||
|
openEventSource();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (gameInherited) {
|
||||||
|
const serverData = await connectQuery.refetch().then(r => {
|
||||||
|
if (r.error) throw r.error;
|
||||||
|
return r.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ('undefined' === typeof serverData.users || null === serverData.users) {
|
||||||
|
showOverlay('This channel does not exists!', <a href="/play" target="_self">Restart game!</a>);
|
||||||
|
console.error('This channel does not exists!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcUsersRef.current = serverData.users;
|
||||||
|
openEventSource();
|
||||||
|
wInit(serverData.revealedCells || []);
|
||||||
|
} else {
|
||||||
|
await startMutation.mutateAsync();
|
||||||
|
openEventSource();
|
||||||
|
wInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
isEnvDev && console.info('Connection initialised — joining channel');
|
||||||
|
await joinMutation.mutateAsync();
|
||||||
|
} catch (e) {
|
||||||
|
isEnvDev && console.error('Connection error', e);
|
||||||
|
setTimeout(() => window.location.reload(), 500);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
window.addEventListener('pagehide', () => navigator.sendBeacon('/api/game/leave/' + gameAssoc));
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
/** UI-facing callbacks */
|
||||||
|
|
||||||
|
const onClick = async coords => {
|
||||||
|
const activeColor = activePlayerRef.current ? 'blue' : 'red';
|
||||||
|
if (activeColor !== webPlayerRef.current) return;
|
||||||
|
|
||||||
|
const [r, c] = coords;
|
||||||
|
if (cells[r]?.[c]?.active) return;
|
||||||
|
|
||||||
|
const stepElapsed = getStepElapsed(activePlayerRef.current, isGameRunningRef.current);
|
||||||
|
const dataPack = { coords, player: activeColor, bomb: bombSelectedRef.current, resign: null, stepElapsed };
|
||||||
|
|
||||||
|
if (connectionLostRef.current) {
|
||||||
|
stepCacheRef.current.push(dataPack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await stepMutation.mutateAsync(dataPack);
|
||||||
|
applyStep(result);
|
||||||
|
makeGameEndIfItEnds(result.bluePoints, result.redPoints, false, result.leftMines);
|
||||||
|
} catch (e) {
|
||||||
|
isEnvDev && console.error('Step error', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clickResign = () => {
|
||||||
|
const color = activePlayerRef.current ? 'blue' : 'red';
|
||||||
|
const stepElapsed = getStepElapsed(activePlayerRef.current, isGameRunningRef.current);
|
||||||
|
stepMutation.mutate({ resign: color, stepElapsed });
|
||||||
|
resignProcess(webPlayerRef.current);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resign = () => {
|
||||||
|
const activeColor = activePlayerRef.current ? 'blue' : 'red';
|
||||||
|
if (webPlayerRef.current !== activeColor) return;
|
||||||
|
showOverlay('Are u sure u want to resign?!', (
|
||||||
|
<div className="resign">
|
||||||
|
<a onClick={clickResign}>Yes</a>
|
||||||
|
<a onClick={hideOverlay}>No!</a>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
return { onClick, resign };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useServerCommunication;
|
||||||
53
assets/js/mine-seeker/hooks/useStepTimer.jsx
Normal file
53
assets/js/mine-seeker/hooks/useStepTimer.jsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useRef } from 'react';
|
||||||
|
|
||||||
|
const useStepTimer = () => {
|
||||||
|
// Record when the current turn started (timestamp)
|
||||||
|
const turnStartTimeRef = useRef(null);
|
||||||
|
// Flag to track if we've already recorded a turn start
|
||||||
|
const turnStartedRef = useRef(false);
|
||||||
|
|
||||||
|
const getStepElapsed = (currentActivePlayer, isGameRunning) => {
|
||||||
|
// If game not running, return 0
|
||||||
|
if (!isGameRunning) return 0;
|
||||||
|
|
||||||
|
// Only initialize the turn timer ONCE per call to getStepElapsed
|
||||||
|
// This prevents resetting on multiple calls
|
||||||
|
if (!turnStartedRef.current) {
|
||||||
|
turnStartTimeRef.current = Date.now();
|
||||||
|
turnStartedRef.current = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After initialization, just calculate elapsed time
|
||||||
|
if (turnStartTimeRef.current) {
|
||||||
|
return Math.floor((Date.now() - turnStartTimeRef.current) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetStepTimer = () => {
|
||||||
|
turnStartTimeRef.current = null;
|
||||||
|
turnStartedRef.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call this when we know a turn has actually changed (from server response)
|
||||||
|
const startNewTurn = () => {
|
||||||
|
turnStartTimeRef.current = Date.now();
|
||||||
|
turnStartedRef.current = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { getStepElapsed, resetStepTimer, startNewTurn };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStepTimer;
|
||||||
|
|
||||||
88
assets/js/mine-seeker/utils/constants.jsx
Normal file
88
assets/js/mine-seeker/utils/constants.jsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const ROWS = 16;
|
||||||
|
export const COLS = 16;
|
||||||
|
export const IMG = '/images/';
|
||||||
|
|
||||||
|
export const WAVES = {
|
||||||
|
1: 'bg-wave-1-outbg.png',
|
||||||
|
2: 'bg-wave-1-outbg.png',
|
||||||
|
3: 'bg-wave-2-outbg.png',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IMAGES = {
|
||||||
|
target: `${IMG}bg-target-outbg.png`,
|
||||||
|
bomb: `${IMG}bg-bomb-outbg.png`,
|
||||||
|
bombDisabled: `${IMG}bg-bomb-disabled-outbg.png`,
|
||||||
|
bombExploded: `${IMG}bg-bomb-exploded-outbg.png`,
|
||||||
|
bombEmpty: `${IMG}bg-bomb-empty-outbg.png`,
|
||||||
|
leftMine: `${IMG}bg-left-mine-outbg.png`,
|
||||||
|
cursor: color => `${IMG}bg-cursor-${color}-outbg.png`,
|
||||||
|
figure: color => `${IMG}bg-figure-${color}-outbg.png`,
|
||||||
|
flag: player => `${IMG}bg-flag-${player}-outbg.png`,
|
||||||
|
last: color => `${IMG}bg-last-${color}-outbg.png`,
|
||||||
|
wave: n => `${IMG}${WAVES[n]}`,
|
||||||
|
bombPos: (hor, vert) => `${IMG}bg-bomb-${hor}-${vert}-outbg.png`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PLAYER_DEF = {
|
||||||
|
name: '...', desc: '', active: false, mines: 0, haveBomb: true, enabledBomb: true,
|
||||||
|
registered: false, avatar: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DESC = {
|
||||||
|
buddy: <div>Your buddy is <br />making a <br />move.</div>,
|
||||||
|
you: <div>It is your turn! <br />Make a move.</div>,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BOMB_SYMBOLS = [
|
||||||
|
[null, null], [0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2],
|
||||||
|
[null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
|
||||||
|
[null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
|
||||||
|
[null, null], [null, null],
|
||||||
|
];
|
||||||
|
|
||||||
|
export const bombRadius = (row, col, rows, cols) => {
|
||||||
|
const centre = 1 < row && row < rows - 2 && 1 < col && col < cols - 2;
|
||||||
|
if (!centre) {
|
||||||
|
col = Math.max(2, Math.min(col, cols - 3));
|
||||||
|
row = Math.max(2, Math.min(row, rows - 3));
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
[row, col], [row - 2, col - 2], [row - 2, col], [row - 2, col + 2],
|
||||||
|
[row, col - 2], [row, col + 2], [row + 2, col - 2], [row + 2, col],
|
||||||
|
[row + 2, col + 2], [row - 2, col + 1], [row - 2, col - 1],
|
||||||
|
[row - 1, col - 2], [row - 1, col - 1], [row - 1, col], [row - 1, col + 1], [row - 1, col + 2],
|
||||||
|
[row, col - 1], [row, col + 1], [row + 1, col - 2], [row + 1, col - 1], [row + 1, col],
|
||||||
|
[row + 1, col + 1], [row + 1, col + 2], [row + 2, col - 1], [row + 2, col + 1],
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const patchCells = (prev, patches) => {
|
||||||
|
const next = prev.map(r => [...r]);
|
||||||
|
for (const { row, col, ...rest } of patches) {
|
||||||
|
next[row][col] = { ...next[row][col], ...rest };
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initCells = () =>
|
||||||
|
Array.from({ length: ROWS }, () =>
|
||||||
|
Array.from({ length: COLS }, () => ({
|
||||||
|
currentImage: IMAGES.wave(Math.floor(Math.random() * 3) + 1),
|
||||||
|
currentObj: 'w',
|
||||||
|
active: false,
|
||||||
|
lastClickedRed: false,
|
||||||
|
lastClickedBlue: false,
|
||||||
|
bombTargetArea: null,
|
||||||
|
})),
|
||||||
|
);
|
||||||
10
assets/js/mine-seeker/utils/index.js
Normal file
10
assets/js/mine-seeker/utils/index.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { DESC, IMAGES, BOMB_SYMBOLS, PLAYER_DEF, bombRadius, initCells, patchCells } from './constants';
|
||||||
37
assets/js/passkey.jsx
Normal file
37
assets/js/passkey.jsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import PasskeyManager from './components/PasskeyManager';
|
||||||
|
import PasskeyLogin from './components/PasskeyLogin';
|
||||||
|
|
||||||
|
const passkeyManagerRoot = document.getElementById('passkey-manager-root');
|
||||||
|
|
||||||
|
if (passkeyManagerRoot) {
|
||||||
|
const credentials = JSON.parse(passkeyManagerRoot.dataset.credentials || '[]');
|
||||||
|
const apiRoutes = JSON.parse(passkeyManagerRoot.dataset.apiRoutes || '{}');
|
||||||
|
|
||||||
|
createRoot(passkeyManagerRoot).render(
|
||||||
|
<PasskeyManager
|
||||||
|
credentials={credentials}
|
||||||
|
apiRoutes={apiRoutes}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const passkeyLoginRoot = document.getElementById('passkey-login-root');
|
||||||
|
|
||||||
|
if (passkeyLoginRoot) {
|
||||||
|
const apiRoutes = JSON.parse(passkeyLoginRoot.dataset.apiRoutes || '{}');
|
||||||
|
|
||||||
|
createRoot(passkeyLoginRoot).render(
|
||||||
|
<PasskeyLogin apiRoutes={apiRoutes} />,
|
||||||
|
);
|
||||||
|
}
|
||||||
31
assets/js/profile.jsx
Normal file
31
assets/js/profile.jsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import ProfileCharts from './components/ProfileCharts';
|
||||||
|
import BattleDialog from './components/BattleDialog';
|
||||||
|
import AvatarUpload from './components/AvatarUpload';
|
||||||
|
|
||||||
|
const avatarRoot = document.getElementById('profile-avatar-root');
|
||||||
|
if (avatarRoot) {
|
||||||
|
const { uploadUrl, thumbUrl, initials } = avatarRoot.dataset;
|
||||||
|
createRoot(avatarRoot).render(
|
||||||
|
<AvatarUpload
|
||||||
|
uploadUrl={uploadUrl}
|
||||||
|
initialThumbUrl={thumbUrl || null}
|
||||||
|
initials={initials}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chartsRoot = document.getElementById('profile-charts-root');
|
||||||
|
if (chartsRoot) {
|
||||||
|
createRoot(chartsRoot).render(
|
||||||
|
<ProfileCharts chartData={JSON.parse(chartsRoot.dataset.chartData)} />,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const battleRoot = document.getElementById('profile-battle-root');
|
||||||
|
if (battleRoot) {
|
||||||
|
createRoot(battleRoot).render(
|
||||||
|
<BattleDialog games={JSON.parse(battleRoot.dataset.games)} />,
|
||||||
|
);
|
||||||
|
}
|
||||||
40
bin/console
40
bin/console
@@ -1,29 +1,39 @@
|
|||||||
#!/usr/bin/env php
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Kernel;
|
||||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
use Symfony\Component\Debug\Debug;
|
use Symfony\Component\Debug\Debug;
|
||||||
|
use Symfony\Component\Dotenv\Dotenv;
|
||||||
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
|
|
||||||
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
|
|
||||||
//umask(0000);
|
|
||||||
|
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
|
|
||||||
/**
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
* @var Composer\Autoload\ClassLoader $loader
|
|
||||||
*/
|
|
||||||
$loader = require __DIR__.'/../app/autoload.php';
|
|
||||||
|
|
||||||
$input = new ArgvInput();
|
if (!class_exists(Application::class)) {
|
||||||
$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev');
|
throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
|
||||||
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
|
|
||||||
|
|
||||||
if ($debug) {
|
|
||||||
Debug::enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$kernel = new AppKernel($env, $debug);
|
if (!isset($_SERVER['APP_ENV'])) {
|
||||||
|
if (!class_exists(Dotenv::class)) {
|
||||||
|
throw new \RuntimeException('APP_ENV environment variable is not defined. You need to define environment variables for configuration or add "symfony/dotenv" as a Composer dependency to load variables from a .env file.');
|
||||||
|
}
|
||||||
|
(new Dotenv())->load(__DIR__.'/../.env');
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = new ArgvInput();
|
||||||
|
$env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true);
|
||||||
|
$debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption('--no-debug', true);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
umask(0000);
|
||||||
|
|
||||||
|
if (class_exists(Debug::class)) {
|
||||||
|
Debug::enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel = new Kernel($env, $debug);
|
||||||
$application = new Application($kernel);
|
$application = new Application($kernel);
|
||||||
$application->run($input);
|
$application->run($input);
|
||||||
|
|||||||
31
bin/generate-mercure-jwt.php
Executable file
31
bin/generate-mercure-jwt.php
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
|
$secret = bin2hex(random_bytes(32));
|
||||||
|
|
||||||
|
$publisherToken = JWT::encode(
|
||||||
|
['mercure' => ['publish' => ['*']]],
|
||||||
|
$secret,
|
||||||
|
'HS256'
|
||||||
|
);
|
||||||
|
|
||||||
|
$subscriberToken = JWT::encode(
|
||||||
|
['mercure' => ['subscribe' => ['*']]],
|
||||||
|
$secret,
|
||||||
|
'HS256'
|
||||||
|
);
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
echo "# ── .env ──────────────────────────────────────────────────────────────" . PHP_EOL;
|
||||||
|
echo "MERCURE_JWT_SECRET=\"{$secret}\"" . PHP_EOL;
|
||||||
|
echo "MERCURE_JWT_TOKEN={$publisherToken}" . PHP_EOL;
|
||||||
|
echo "MERCURE_SUBSCRIBER_JWT={$subscriberToken}" . PHP_EOL;
|
||||||
|
echo PHP_EOL;
|
||||||
|
echo "# ── /etc/caddy/conf.d/mine.caddy (inside the mercure {} block) ───────" . PHP_EOL;
|
||||||
|
echo "publisher_jwt {$secret} HS256" . PHP_EOL;
|
||||||
|
echo "subscriber_jwt {$secret} HS256" . PHP_EOL;
|
||||||
|
echo PHP_EOL;
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once dirname(__FILE__).'/../var/SymfonyRequirements.php';
|
|
||||||
|
|
||||||
$lineSize = 70;
|
|
||||||
$symfonyRequirements = new SymfonyRequirements();
|
|
||||||
$iniPath = $symfonyRequirements->getPhpIniConfigPath();
|
|
||||||
|
|
||||||
echo_title('Symfony Requirements Checker');
|
|
||||||
|
|
||||||
echo '> PHP is using the following php.ini file:'.PHP_EOL;
|
|
||||||
if ($iniPath) {
|
|
||||||
echo_style('green', ' '.$iniPath);
|
|
||||||
} else {
|
|
||||||
echo_style('yellow', ' WARNING: No configuration file (php.ini) used by PHP!');
|
|
||||||
}
|
|
||||||
|
|
||||||
echo PHP_EOL.PHP_EOL;
|
|
||||||
|
|
||||||
echo '> Checking Symfony requirements:'.PHP_EOL.' ';
|
|
||||||
|
|
||||||
$messages = array();
|
|
||||||
foreach ($symfonyRequirements->getRequirements() as $req) {
|
|
||||||
if ($helpText = get_error_message($req, $lineSize)) {
|
|
||||||
echo_style('red', 'E');
|
|
||||||
$messages['error'][] = $helpText;
|
|
||||||
} else {
|
|
||||||
echo_style('green', '.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$checkPassed = empty($messages['error']);
|
|
||||||
|
|
||||||
foreach ($symfonyRequirements->getRecommendations() as $req) {
|
|
||||||
if ($helpText = get_error_message($req, $lineSize)) {
|
|
||||||
echo_style('yellow', 'W');
|
|
||||||
$messages['warning'][] = $helpText;
|
|
||||||
} else {
|
|
||||||
echo_style('green', '.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($checkPassed) {
|
|
||||||
echo_block('success', 'OK', 'Your system is ready to run Symfony projects');
|
|
||||||
} else {
|
|
||||||
echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects');
|
|
||||||
|
|
||||||
echo_title('Fix the following mandatory requirements', 'red');
|
|
||||||
|
|
||||||
foreach ($messages['error'] as $helpText) {
|
|
||||||
echo ' * '.$helpText.PHP_EOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($messages['warning'])) {
|
|
||||||
echo_title('Optional recommendations to improve your setup', 'yellow');
|
|
||||||
|
|
||||||
foreach ($messages['warning'] as $helpText) {
|
|
||||||
echo ' * '.$helpText.PHP_EOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo PHP_EOL;
|
|
||||||
echo_style('title', 'Note');
|
|
||||||
echo ' The command console could use a different php.ini file'.PHP_EOL;
|
|
||||||
echo_style('title', '~~~~');
|
|
||||||
echo ' than the one used with your web server. To be on the'.PHP_EOL;
|
|
||||||
echo ' safe side, please check the requirements from your web'.PHP_EOL;
|
|
||||||
echo ' server using the ';
|
|
||||||
echo_style('yellow', 'web/config.php');
|
|
||||||
echo ' script.'.PHP_EOL;
|
|
||||||
echo PHP_EOL;
|
|
||||||
|
|
||||||
exit($checkPassed ? 0 : 1);
|
|
||||||
|
|
||||||
function get_error_message(Requirement $requirement, $lineSize)
|
|
||||||
{
|
|
||||||
if ($requirement->isFulfilled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL;
|
|
||||||
$errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL;
|
|
||||||
|
|
||||||
return $errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
function echo_title($title, $style = null)
|
|
||||||
{
|
|
||||||
$style = $style ?: 'title';
|
|
||||||
|
|
||||||
echo PHP_EOL;
|
|
||||||
echo_style($style, $title.PHP_EOL);
|
|
||||||
echo_style($style, str_repeat('~', strlen($title)).PHP_EOL);
|
|
||||||
echo PHP_EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
function echo_style($style, $message)
|
|
||||||
{
|
|
||||||
// ANSI color codes
|
|
||||||
$styles = array(
|
|
||||||
'reset' => "\033[0m",
|
|
||||||
'red' => "\033[31m",
|
|
||||||
'green' => "\033[32m",
|
|
||||||
'yellow' => "\033[33m",
|
|
||||||
'error' => "\033[37;41m",
|
|
||||||
'success' => "\033[37;42m",
|
|
||||||
'title' => "\033[34m",
|
|
||||||
);
|
|
||||||
$supports = has_color_support();
|
|
||||||
|
|
||||||
echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function echo_block($style, $title, $message)
|
|
||||||
{
|
|
||||||
$message = ' '.trim($message).' ';
|
|
||||||
$width = strlen($message);
|
|
||||||
|
|
||||||
echo PHP_EOL.PHP_EOL;
|
|
||||||
|
|
||||||
echo_style($style, str_repeat(' ', $width));
|
|
||||||
echo PHP_EOL;
|
|
||||||
echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT));
|
|
||||||
echo PHP_EOL;
|
|
||||||
echo_style($style, $message);
|
|
||||||
echo PHP_EOL;
|
|
||||||
echo_style($style, str_repeat(' ', $width));
|
|
||||||
echo PHP_EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
function has_color_support()
|
|
||||||
{
|
|
||||||
static $support;
|
|
||||||
|
|
||||||
if (null === $support) {
|
|
||||||
if (DIRECTORY_SEPARATOR == '\\') {
|
|
||||||
$support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
|
|
||||||
} else {
|
|
||||||
$support = function_exists('posix_isatty') && @posix_isatty(STDOUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $support;
|
|
||||||
}
|
|
||||||
887
bun.lock
Normal file
887
bun.lock
Normal file
@@ -0,0 +1,887 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 0,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "mine-seeker",
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.14.0",
|
||||||
|
"@emotion/styled": "^11.14.1",
|
||||||
|
"@fontsource/changa-one": "^5.2.8",
|
||||||
|
"@fontsource/open-sans": "^5.2.7",
|
||||||
|
"@fontsource/rajdhani": "^5.2.7",
|
||||||
|
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||||
|
"@mui/material": "^9.0.0",
|
||||||
|
"@mui/x-charts": "^9.0.1",
|
||||||
|
"@tanstack/react-query": "^5.0.0",
|
||||||
|
"howler": "^2.1.2",
|
||||||
|
"lodash": "^4.18.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/eslintrc": "^3.3.5",
|
||||||
|
"@eslint/js": "^9.0.0",
|
||||||
|
"@stylistic/eslint-plugin": "^4.0.0",
|
||||||
|
"@vitejs/plugin-react": "^6.0.1",
|
||||||
|
"eslint": "^9.0.0",
|
||||||
|
"eslint-plugin-react": "^7.0.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
|
"globals": "^15.0.0",
|
||||||
|
"sass": "^1.77.0",
|
||||||
|
"vite": "^8.0.8",
|
||||||
|
"vite-plugin-symfony": "^8.2.4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@babel/code-frame": ["@babel/code-frame@7.29.0", "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
|
||||||
|
|
||||||
|
"@babel/generator": ["@babel/generator@7.29.1", "http://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
|
||||||
|
|
||||||
|
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "http://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
||||||
|
|
||||||
|
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "http://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
|
||||||
|
|
||||||
|
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "http://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "http://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
||||||
|
|
||||||
|
"@babel/parser": ["@babel/parser@7.29.2", "http://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
||||||
|
|
||||||
|
"@babel/runtime": ["@babel/runtime@7.29.2", "http://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
|
||||||
|
|
||||||
|
"@babel/template": ["@babel/template@7.28.6", "http://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
|
||||||
|
|
||||||
|
"@babel/traverse": ["@babel/traverse@7.29.0", "http://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
|
||||||
|
|
||||||
|
"@babel/types": ["@babel/types@7.29.0", "http://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||||
|
|
||||||
|
"@emnapi/core": ["@emnapi/core@1.9.2", "http://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
||||||
|
|
||||||
|
"@emnapi/runtime": ["@emnapi/runtime@1.9.2", "http://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
||||||
|
|
||||||
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "http://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||||
|
|
||||||
|
"@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "http://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="],
|
||||||
|
|
||||||
|
"@emotion/cache": ["@emotion/cache@11.14.0", "http://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="],
|
||||||
|
|
||||||
|
"@emotion/hash": ["@emotion/hash@0.9.2", "http://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="],
|
||||||
|
|
||||||
|
"@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.4.0", "http://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw=="],
|
||||||
|
|
||||||
|
"@emotion/memoize": ["@emotion/memoize@0.9.0", "http://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="],
|
||||||
|
|
||||||
|
"@emotion/react": ["@emotion/react@11.14.0", "http://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="],
|
||||||
|
|
||||||
|
"@emotion/serialize": ["@emotion/serialize@1.3.3", "http://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="],
|
||||||
|
|
||||||
|
"@emotion/sheet": ["@emotion/sheet@1.4.0", "http://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="],
|
||||||
|
|
||||||
|
"@emotion/styled": ["@emotion/styled@11.14.1", "http://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", "react": ">=16.8.0" } }, "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw=="],
|
||||||
|
|
||||||
|
"@emotion/unitless": ["@emotion/unitless@0.10.0", "http://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="],
|
||||||
|
|
||||||
|
"@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "http://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="],
|
||||||
|
|
||||||
|
"@emotion/utils": ["@emotion/utils@1.4.2", "http://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="],
|
||||||
|
|
||||||
|
"@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "http://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="],
|
||||||
|
|
||||||
|
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "http://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
||||||
|
|
||||||
|
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "http://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||||
|
|
||||||
|
"@eslint/config-array": ["@eslint/config-array@0.21.2", "http://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
|
||||||
|
|
||||||
|
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "http://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
|
||||||
|
|
||||||
|
"@eslint/core": ["@eslint/core@0.17.0", "http://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "http://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
|
||||||
|
|
||||||
|
"@eslint/js": ["@eslint/js@9.39.4", "http://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="],
|
||||||
|
|
||||||
|
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "http://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
|
||||||
|
|
||||||
|
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "http://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
|
||||||
|
|
||||||
|
"@fontsource/changa-one": ["@fontsource/changa-one@5.2.8", "http://registry.npmjs.org/@fontsource/changa-one/-/changa-one-5.2.8.tgz", {}, "sha512-gagiU8sMWLs9ejh41NmrYlGdgasSYWFegz5/+22WqYdJVS9HZbaUEXj/6jj3ZKgi+dQZT0kYI+Nha2UQGbO/mA=="],
|
||||||
|
|
||||||
|
"@fontsource/open-sans": ["@fontsource/open-sans@5.2.7", "", {}, "sha512-8yfgDYjE5O0vmTPdrcjV35y4yMnctsokmi9gN49Gcsr0sjzkMkR97AnKDe6OqZh2SFkYlR28fxOvi21bYEgMSw=="],
|
||||||
|
|
||||||
|
"@fontsource/rajdhani": ["@fontsource/rajdhani@5.2.7", "http://registry.npmjs.org/@fontsource/rajdhani/-/rajdhani-5.2.7.tgz", {}, "sha512-7Gy10U688fCdeFfYKebUF2TZotdgH/ghKyMsseXPmB60lpaUHC8aoCSJl5/OpZ+KHKSU2TqBfKfteVkcIXxTAQ=="],
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-free": ["@fortawesome/fontawesome-free@7.2.0", "http://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.2.0.tgz", {}, "sha512-3DguDv/oUE+7vjMeTSOjCSG+KeawgVQOHrKRnvUuqYh1mfArrh7s+s8hXW3e4RerBA1+Wh+hBqf8sJNpqNrBWg=="],
|
||||||
|
|
||||||
|
"@humanfs/core": ["@humanfs/core@0.19.1", "http://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||||
|
|
||||||
|
"@humanfs/node": ["@humanfs/node@0.16.7", "http://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
|
||||||
|
|
||||||
|
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "http://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||||
|
|
||||||
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "http://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "http://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "http://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "http://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "http://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
|
"@mui/core-downloads-tracker": ["@mui/core-downloads-tracker@9.0.0", "http://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-9.0.0.tgz", {}, "sha512-uwQNGkhv0lf7ufxw6QXev77BW6pWbW+7uxYjU5+rfp4lBkFtMEgJCsarTM3Tn+i0lGx6+Ol2u88JdGXr0GDskA=="],
|
||||||
|
|
||||||
|
"@mui/material": ["@mui/material@9.0.0", "http://registry.npmjs.org/@mui/material/-/material-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2", "@mui/core-downloads-tracker": "^9.0.0", "@mui/system": "^9.0.0", "@mui/types": "^9.0.0", "@mui/utils": "^9.0.0", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", "csstype": "^3.2.3", "prop-types": "^15.8.1", "react-is": "^19.2.4", "react-transition-group": "^4.4.5" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/material-pigment-css": "^9.0.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@mui/material-pigment-css", "@types/react"] }, "sha512-+VP/oQCDhDR87NQQgXnNBG8dwy6GNuQLnenS1pZvkbn2dKFSxRSRMybTpH9xUxXP+316mlYDy5CSbYtusnCWtw=="],
|
||||||
|
|
||||||
|
"@mui/private-theming": ["@mui/private-theming@9.0.0", "http://registry.npmjs.org/@mui/private-theming/-/private-theming-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2", "@mui/utils": "^9.0.0", "prop-types": "^15.8.1" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-JtuZoaiCqwD6vjgYu6Xp3T7DZkrxJlgtDz5yESzhI34fEX5hHMh2VJUbuL9UOg8xrfIFMrq6dcYoH/7Zi4G0RA=="],
|
||||||
|
|
||||||
|
"@mui/styled-engine": ["@mui/styled-engine@9.0.0", "http://registry.npmjs.org/@mui/styled-engine/-/styled-engine-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "csstype": "^3.2.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled"] }, "sha512-9RLGdX4Jg0aQPRuvqh/OLzYSPlgd5zyEw5/1HIRfdavSiOd03WtUaGZH9/w1RoTYuRKwpgy0hpIFaMHIqPVIWg=="],
|
||||||
|
|
||||||
|
"@mui/system": ["@mui/system@9.0.0", "http://registry.npmjs.org/@mui/system/-/system-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2", "@mui/private-theming": "^9.0.0", "@mui/styled-engine": "^9.0.0", "@mui/types": "^9.0.0", "@mui/utils": "^9.0.0", "clsx": "^2.1.1", "csstype": "^3.2.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@types/react"] }, "sha512-YnC5Zg6j04IxiLc/boAKs0464jfZlLFVa7mf5E8lF0XOtZVUvG6R6gJK50lgUYdaaLdyLfxF6xR7LaPuEpeT/g=="],
|
||||||
|
|
||||||
|
"@mui/types": ["@mui/types@9.0.0", "http://registry.npmjs.org/@mui/types/-/types-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-i1cuFCAWN44b3AJWO7mh7tuh1sqbQSeVr/94oG0TX5uXivac8XalgE4/6fQZcmGZigzbQ35IXxj/4jLpRIBYZg=="],
|
||||||
|
|
||||||
|
"@mui/utils": ["@mui/utils@9.0.0", "http://registry.npmjs.org/@mui/utils/-/utils-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.29.2", "@mui/types": "^9.0.0", "@types/prop-types": "^15.7.15", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^19.2.4" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-bQcqyg/gjULUqTuyUjSAFr6LQGLvtkNtDbJerAtoUn9kGZ0hg5QJiN1PLHMLbeFpe3te1831uq7GFl2ITokGdg=="],
|
||||||
|
|
||||||
|
"@mui/x-charts": ["@mui/x-charts@9.0.1", "http://registry.npmjs.org/@mui/x-charts/-/x-charts-9.0.1.tgz", { "dependencies": { "@babel/runtime": "^7.28.6", "@mui/utils": "9.0.0", "@mui/x-charts-vendor": "^9.0.0", "@mui/x-internal-gestures": "^9.0.0", "@mui/x-internals": "^9.0.0", "bezier-easing": "^2.1.0", "clsx": "^2.1.1", "prop-types": "^15.8.1", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", "@mui/material": "^7.3.0 || ^9.0.0", "@mui/system": "^7.3.0 || ^9.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled"] }, "sha512-0LyhlGhUm07wGJY0d0U+hSljGS1EHKWgPBsTJ/lBNGDrNc4DI9zSbp4h802LN/eLwMUVXJSI7DH2W3Ef3WsqnQ=="],
|
||||||
|
|
||||||
|
"@mui/x-charts-vendor": ["@mui/x-charts-vendor@9.0.0", "http://registry.npmjs.org/@mui/x-charts-vendor/-/x-charts-vendor-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.28.6", "@types/d3-array": "^3.2.2", "@types/d3-color": "^3.1.3", "@types/d3-format": "^3.0.4", "@types/d3-interpolate": "^3.0.4", "@types/d3-path": "^3.1.1", "@types/d3-scale": "^4.0.9", "@types/d3-shape": "^3.1.8", "@types/d3-time": "^3.0.4", "@types/d3-time-format": "^4.0.3", "@types/d3-timer": "^3.0.2", "d3-array": "^3.2.4", "d3-color": "^3.1.0", "d3-format": "^3.1.2", "d3-interpolate": "^3.0.1", "d3-path": "^3.1.0", "d3-scale": "^4.0.2", "d3-shape": "^3.2.0", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", "d3-timer": "^3.0.1", "flatqueue": "^3.0.0", "internmap": "^2.0.3" } }, "sha512-Do91i+fZiNj/4LN5oaGpJoutolzDBDwdfw6tHrx2LKXDMCRlaImCfreLbdbkk7dFsi9fuIP7hWiMV4vDJKPJTA=="],
|
||||||
|
|
||||||
|
"@mui/x-internal-gestures": ["@mui/x-internal-gestures@9.0.0", "http://registry.npmjs.org/@mui/x-internal-gestures/-/x-internal-gestures-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.28.6" } }, "sha512-+fW1EUai25GJbivGRsi3GX4GYsSvzFPvUEjmMgB4POkRBDjrEZNaLdVWfapT6DlWv/Vfbi08bYSuyvhPXGMZjw=="],
|
||||||
|
|
||||||
|
"@mui/x-internals": ["@mui/x-internals@9.0.0", "http://registry.npmjs.org/@mui/x-internals/-/x-internals-9.0.0.tgz", { "dependencies": { "@babel/runtime": "^7.28.6", "@mui/utils": "9.0.0", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-E/4rdg69JjhyybpPGypCjAKSKLLnSdCFM+O6P/nkUg47+qt3uftxQEhjQO53rcn6ahHl6du/uNZ9BLgeY6kYxQ=="],
|
||||||
|
|
||||||
|
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.3", "http://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="],
|
||||||
|
|
||||||
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "http://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
|
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "http://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||||
|
|
||||||
|
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "http://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||||
|
|
||||||
|
"@oxc-project/types": ["@oxc-project/types@0.124.0", "http://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="],
|
||||||
|
|
||||||
|
"@parcel/watcher": ["@parcel/watcher@2.5.6", "http://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", { "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", "@parcel/watcher-freebsd-x64": "2.5.6", "@parcel/watcher-linux-arm-glibc": "2.5.6", "@parcel/watcher-linux-arm-musl": "2.5.6", "@parcel/watcher-linux-arm64-glibc": "2.5.6", "@parcel/watcher-linux-arm64-musl": "2.5.6", "@parcel/watcher-linux-x64-glibc": "2.5.6", "@parcel/watcher-linux-x64-musl": "2.5.6", "@parcel/watcher-win32-arm64": "2.5.6", "@parcel/watcher-win32-ia32": "2.5.6", "@parcel/watcher-win32-x64": "2.5.6" } }, "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", { "os": "android", "cpu": "arm64" }, "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", { "os": "linux", "cpu": "arm" }, "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", { "os": "linux", "cpu": "arm" }, "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", { "os": "linux", "cpu": "x64" }, "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.6", "http://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", { "os": "linux", "cpu": "x64" }, "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.6", "http://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g=="],
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "http://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="],
|
||||||
|
|
||||||
|
"@polka/url": ["@polka/url@1.0.0-next.29", "http://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||||
|
|
||||||
|
"@popperjs/core": ["@popperjs/core@2.11.8", "http://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="],
|
||||||
|
|
||||||
|
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.7", "http://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", {}, "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA=="],
|
||||||
|
|
||||||
|
"@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@4.4.1", "http://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.4.1.tgz", { "dependencies": { "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ=="],
|
||||||
|
|
||||||
|
"@tanstack/query-core": ["@tanstack/query-core@5.97.0", "http://registry.npmjs.org/@tanstack/query-core/-/query-core-5.97.0.tgz", {}, "sha512-QdpLP5VzVMgo4VtaPppRA2W04UFjIqX+bxke/ZJhE5cfd5UPkRzqIAJQt9uXkQJjqE8LBOMbKv7f8HCsZltXlg=="],
|
||||||
|
|
||||||
|
"@tanstack/react-query": ["@tanstack/react-query@5.97.0", "http://registry.npmjs.org/@tanstack/react-query/-/react-query-5.97.0.tgz", { "dependencies": { "@tanstack/query-core": "5.97.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-y4So4eGcQoK2WVMAcDNZE9ofB/p5v1OlKvtc1F3uqHwrtifobT7q+ZnXk2mRkc8E84HKYSlAE9z6HXl2V0+ySQ=="],
|
||||||
|
|
||||||
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "http://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
|
"@types/d3-array": ["@types/d3-array@3.2.2", "http://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
||||||
|
|
||||||
|
"@types/d3-color": ["@types/d3-color@3.1.3", "http://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
|
||||||
|
|
||||||
|
"@types/d3-format": ["@types/d3-format@3.0.4", "http://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="],
|
||||||
|
|
||||||
|
"@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "http://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
|
||||||
|
|
||||||
|
"@types/d3-path": ["@types/d3-path@3.1.1", "http://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
|
||||||
|
|
||||||
|
"@types/d3-scale": ["@types/d3-scale@4.0.9", "http://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
|
||||||
|
|
||||||
|
"@types/d3-shape": ["@types/d3-shape@3.1.8", "http://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="],
|
||||||
|
|
||||||
|
"@types/d3-time": ["@types/d3-time@3.0.4", "http://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
|
||||||
|
|
||||||
|
"@types/d3-time-format": ["@types/d3-time-format@4.0.3", "http://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="],
|
||||||
|
|
||||||
|
"@types/d3-timer": ["@types/d3-timer@3.0.2", "http://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
|
||||||
|
|
||||||
|
"@types/estree": ["@types/estree@1.0.8", "http://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
|
"@types/json-schema": ["@types/json-schema@7.0.15", "http://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||||
|
|
||||||
|
"@types/parse-json": ["@types/parse-json@4.0.2", "http://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
||||||
|
|
||||||
|
"@types/prop-types": ["@types/prop-types@15.7.15", "http://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
|
||||||
|
|
||||||
|
"@types/react": ["@types/react@19.2.14", "http://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||||
|
|
||||||
|
"@types/react-transition-group": ["@types/react-transition-group@4.4.12", "http://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", { "peerDependencies": { "@types/react": "*" } }, "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.1", "http://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.1.tgz", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.1", "@typescript-eslint/types": "^8.58.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.1", "http://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1" } }, "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.1", "http://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "http://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.1", "http://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz", { "dependencies": { "@typescript-eslint/project-service": "8.58.1", "@typescript-eslint/tsconfig-utils": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.1", "http://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.1.tgz", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.1", "http://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz", { "dependencies": { "@typescript-eslint/types": "8.58.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ=="],
|
||||||
|
|
||||||
|
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.1", "http://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.7" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ=="],
|
||||||
|
|
||||||
|
"acorn": ["acorn@8.16.0", "http://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
||||||
|
|
||||||
|
"acorn-jsx": ["acorn-jsx@5.3.2", "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||||
|
|
||||||
|
"ajv": ["ajv@6.14.0", "http://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
||||||
|
|
||||||
|
"ansi-styles": ["ansi-styles@4.3.0", "http://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||||
|
|
||||||
|
"argparse": ["argparse@2.0.1", "http://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||||
|
|
||||||
|
"array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "http://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
|
||||||
|
|
||||||
|
"array-includes": ["array-includes@3.1.9", "http://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
|
||||||
|
|
||||||
|
"array.prototype.findlast": ["array.prototype.findlast@1.2.5", "http://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
|
||||||
|
|
||||||
|
"array.prototype.flat": ["array.prototype.flat@1.3.3", "http://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
|
||||||
|
|
||||||
|
"array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "http://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
|
||||||
|
|
||||||
|
"array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "http://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
|
||||||
|
|
||||||
|
"arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "http://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
|
||||||
|
|
||||||
|
"async-function": ["async-function@1.0.0", "http://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
|
||||||
|
|
||||||
|
"available-typed-arrays": ["available-typed-arrays@1.0.7", "http://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||||
|
|
||||||
|
"babel-plugin-macros": ["babel-plugin-macros@3.1.0", "http://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
|
||||||
|
|
||||||
|
"balanced-match": ["balanced-match@1.0.0", "http://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", {}, "sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg=="],
|
||||||
|
|
||||||
|
"bezier-easing": ["bezier-easing@2.1.0", "http://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", {}, "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="],
|
||||||
|
|
||||||
|
"brace-expansion": ["brace-expansion@1.1.11", "http://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||||
|
|
||||||
|
"braces": ["braces@3.0.3", "http://registry.npmjs.org/braces/-/braces-3.0.3.tgz", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||||
|
|
||||||
|
"call-bind": ["call-bind@1.0.9", "http://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="],
|
||||||
|
|
||||||
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "http://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||||
|
|
||||||
|
"call-bound": ["call-bound@1.0.4", "http://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||||
|
|
||||||
|
"callsites": ["callsites@3.1.0", "http://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||||
|
|
||||||
|
"chalk": ["chalk@4.1.2", "http://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||||
|
|
||||||
|
"chokidar": ["chokidar@4.0.3", "http://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||||
|
|
||||||
|
"clsx": ["clsx@2.1.1", "http://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||||
|
|
||||||
|
"color-convert": ["color-convert@2.0.1", "http://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||||
|
|
||||||
|
"color-name": ["color-name@1.1.4", "http://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||||
|
|
||||||
|
"concat-map": ["concat-map@0.0.1", "http://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||||
|
|
||||||
|
"convert-source-map": ["convert-source-map@1.9.0", "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
|
||||||
|
|
||||||
|
"cosmiconfig": ["cosmiconfig@7.1.0", "http://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="],
|
||||||
|
|
||||||
|
"cross-spawn": ["cross-spawn@7.0.6", "http://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
|
"csstype": ["csstype@3.2.3", "http://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||||
|
|
||||||
|
"d3-array": ["d3-array@3.2.4", "http://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
|
||||||
|
|
||||||
|
"d3-color": ["d3-color@3.1.0", "http://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
|
||||||
|
|
||||||
|
"d3-format": ["d3-format@3.1.2", "http://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="],
|
||||||
|
|
||||||
|
"d3-interpolate": ["d3-interpolate@3.0.1", "http://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
|
||||||
|
|
||||||
|
"d3-path": ["d3-path@3.1.0", "http://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
|
||||||
|
|
||||||
|
"d3-scale": ["d3-scale@4.0.2", "http://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
|
||||||
|
|
||||||
|
"d3-shape": ["d3-shape@3.2.0", "http://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
|
||||||
|
|
||||||
|
"d3-time": ["d3-time@3.1.0", "http://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
|
||||||
|
|
||||||
|
"d3-time-format": ["d3-time-format@4.1.0", "http://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
|
||||||
|
|
||||||
|
"d3-timer": ["d3-timer@3.0.1", "http://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
|
||||||
|
|
||||||
|
"data-view-buffer": ["data-view-buffer@1.0.2", "http://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
|
||||||
|
|
||||||
|
"data-view-byte-length": ["data-view-byte-length@1.0.2", "http://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
|
||||||
|
|
||||||
|
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "http://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.3", "http://registry.npmjs.org/debug/-/debug-4.4.3.tgz", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
"deep-is": ["deep-is@0.1.4", "http://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||||
|
|
||||||
|
"define-data-property": ["define-data-property@1.1.4", "http://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
|
||||||
|
|
||||||
|
"define-properties": ["define-properties@1.2.1", "http://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
|
||||||
|
|
||||||
|
"detect-libc": ["detect-libc@2.1.2", "http://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
|
"doctrine": ["doctrine@2.1.0", "http://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
|
||||||
|
|
||||||
|
"dom-helpers": ["dom-helpers@5.2.1", "http://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
|
||||||
|
|
||||||
|
"dunder-proto": ["dunder-proto@1.0.1", "http://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
|
"error-ex": ["error-ex@1.3.4", "http://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
||||||
|
|
||||||
|
"es-abstract": ["es-abstract@1.24.2", "http://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="],
|
||||||
|
|
||||||
|
"es-define-property": ["es-define-property@1.0.1", "http://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||||
|
|
||||||
|
"es-errors": ["es-errors@1.3.0", "http://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
|
|
||||||
|
"es-iterator-helpers": ["es-iterator-helpers@1.3.2", "http://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="],
|
||||||
|
|
||||||
|
"es-object-atoms": ["es-object-atoms@1.1.1", "http://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||||
|
|
||||||
|
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "http://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||||
|
|
||||||
|
"es-shim-unscopables": ["es-shim-unscopables@1.1.0", "http://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
|
||||||
|
|
||||||
|
"es-to-primitive": ["es-to-primitive@1.3.0", "http://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
|
||||||
|
|
||||||
|
"escape-string-regexp": ["escape-string-regexp@4.0.0", "http://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||||
|
|
||||||
|
"eslint": ["eslint@9.39.4", "http://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
|
||||||
|
|
||||||
|
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "http://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "http://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||||
|
|
||||||
|
"eslint-scope": ["eslint-scope@8.4.0", "http://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||||
|
|
||||||
|
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "http://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
|
||||||
|
|
||||||
|
"espree": ["espree@10.4.0", "http://registry.npmjs.org/espree/-/espree-10.4.0.tgz", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||||
|
|
||||||
|
"esquery": ["esquery@1.7.0", "http://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||||
|
|
||||||
|
"esrecurse": ["esrecurse@4.3.0", "http://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||||
|
|
||||||
|
"estraverse": ["estraverse@5.3.0", "http://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||||
|
|
||||||
|
"esutils": ["esutils@2.0.3", "http://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||||
|
|
||||||
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||||
|
|
||||||
|
"fast-glob": ["fast-glob@3.3.3", "http://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||||
|
|
||||||
|
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "http://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||||
|
|
||||||
|
"fast-levenshtein": ["fast-levenshtein@2.0.6", "http://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||||
|
|
||||||
|
"fastq": ["fastq@1.20.1", "http://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||||
|
|
||||||
|
"fdir": ["fdir@6.5.0", "http://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
|
"file-entry-cache": ["file-entry-cache@8.0.0", "http://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||||
|
|
||||||
|
"fill-range": ["fill-range@7.1.1", "http://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||||
|
|
||||||
|
"find-root": ["find-root@1.1.0", "http://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
|
||||||
|
|
||||||
|
"find-up": ["find-up@5.0.0", "http://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||||
|
|
||||||
|
"flat-cache": ["flat-cache@4.0.1", "http://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||||
|
|
||||||
|
"flatqueue": ["flatqueue@3.0.0", "http://registry.npmjs.org/flatqueue/-/flatqueue-3.0.0.tgz", {}, "sha512-y1deYaVt+lIc/d2uIcWDNd0CrdQTO5xoCjeFdhX0kSXvm2Acm0o+3bAOiYklTEoRyzwio3sv3/IiBZdusbAe2Q=="],
|
||||||
|
|
||||||
|
"flatted": ["flatted@3.4.2", "http://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
|
||||||
|
|
||||||
|
"for-each": ["for-each@0.3.5", "http://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||||
|
|
||||||
|
"fsevents": ["fsevents@2.3.3", "http://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
|
"function-bind": ["function-bind@1.1.2", "http://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||||
|
|
||||||
|
"function.prototype.name": ["function.prototype.name@1.1.8", "http://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
|
||||||
|
|
||||||
|
"functions-have-names": ["functions-have-names@1.2.3", "http://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
|
||||||
|
|
||||||
|
"generator-function": ["generator-function@2.0.1", "http://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
|
||||||
|
|
||||||
|
"get-intrinsic": ["get-intrinsic@1.3.0", "http://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||||
|
|
||||||
|
"get-proto": ["get-proto@1.0.1", "http://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||||
|
|
||||||
|
"get-symbol-description": ["get-symbol-description@1.1.0", "http://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
|
||||||
|
|
||||||
|
"glob-parent": ["glob-parent@6.0.2", "http://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||||
|
|
||||||
|
"globals": ["globals@15.15.0", "http://registry.npmjs.org/globals/-/globals-15.15.0.tgz", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="],
|
||||||
|
|
||||||
|
"globalthis": ["globalthis@1.0.4", "http://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
|
||||||
|
|
||||||
|
"gopd": ["gopd@1.2.0", "http://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||||
|
|
||||||
|
"has-bigints": ["has-bigints@1.1.0", "http://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
|
||||||
|
|
||||||
|
"has-flag": ["has-flag@4.0.0", "http://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||||
|
|
||||||
|
"has-property-descriptors": ["has-property-descriptors@1.0.2", "http://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
|
||||||
|
|
||||||
|
"has-proto": ["has-proto@1.2.0", "http://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
|
||||||
|
|
||||||
|
"has-symbols": ["has-symbols@1.1.0", "http://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||||
|
|
||||||
|
"has-tostringtag": ["has-tostringtag@1.0.2", "http://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||||
|
|
||||||
|
"hasown": ["hasown@2.0.2", "http://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
|
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "http://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
|
||||||
|
|
||||||
|
"howler": ["howler@2.1.2", "http://registry.npmjs.org/howler/-/howler-2.1.2.tgz", {}, "sha512-oKrTFaVXsDRoB/jik7cEpWKTj7VieoiuzMYJ7E/EU5ayvmpRhumCv3YQ3823zi9VTJkSWAhbryHnlZAionGAJg=="],
|
||||||
|
|
||||||
|
"ignore": ["ignore@5.3.2", "http://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||||
|
|
||||||
|
"immutable": ["immutable@5.1.5", "http://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", {}, "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A=="],
|
||||||
|
|
||||||
|
"import-fresh": ["import-fresh@3.3.1", "http://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||||
|
|
||||||
|
"imurmurhash": ["imurmurhash@0.1.4", "http://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||||
|
|
||||||
|
"internal-slot": ["internal-slot@1.1.0", "http://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
|
||||||
|
|
||||||
|
"internmap": ["internmap@2.0.3", "http://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
|
||||||
|
|
||||||
|
"is-array-buffer": ["is-array-buffer@3.0.5", "http://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
|
||||||
|
|
||||||
|
"is-arrayish": ["is-arrayish@0.2.1", "http://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||||
|
|
||||||
|
"is-async-function": ["is-async-function@2.1.1", "http://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
|
||||||
|
|
||||||
|
"is-bigint": ["is-bigint@1.1.0", "http://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
|
||||||
|
|
||||||
|
"is-boolean-object": ["is-boolean-object@1.2.2", "http://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
|
||||||
|
|
||||||
|
"is-callable": ["is-callable@1.2.7", "http://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
|
||||||
|
|
||||||
|
"is-core-module": ["is-core-module@2.16.1", "http://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
||||||
|
|
||||||
|
"is-data-view": ["is-data-view@1.0.2", "http://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
|
||||||
|
|
||||||
|
"is-date-object": ["is-date-object@1.1.0", "http://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
|
||||||
|
|
||||||
|
"is-extglob": ["is-extglob@2.1.1", "http://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||||
|
|
||||||
|
"is-finalizationregistry": ["is-finalizationregistry@1.1.1", "http://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
|
||||||
|
|
||||||
|
"is-generator-function": ["is-generator-function@1.1.2", "http://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
|
||||||
|
|
||||||
|
"is-glob": ["is-glob@4.0.3", "http://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||||
|
|
||||||
|
"is-map": ["is-map@2.0.3", "http://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
|
||||||
|
|
||||||
|
"is-negative-zero": ["is-negative-zero@2.0.3", "http://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
|
||||||
|
|
||||||
|
"is-number": ["is-number@7.0.0", "http://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||||
|
|
||||||
|
"is-number-object": ["is-number-object@1.1.1", "http://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
|
||||||
|
|
||||||
|
"is-regex": ["is-regex@1.2.1", "http://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
|
||||||
|
|
||||||
|
"is-set": ["is-set@2.0.3", "http://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
|
||||||
|
|
||||||
|
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "http://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
|
||||||
|
|
||||||
|
"is-string": ["is-string@1.1.1", "http://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
|
||||||
|
|
||||||
|
"is-symbol": ["is-symbol@1.1.1", "http://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
|
||||||
|
|
||||||
|
"is-typed-array": ["is-typed-array@1.1.15", "http://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
|
||||||
|
|
||||||
|
"is-weakmap": ["is-weakmap@2.0.2", "http://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
|
||||||
|
|
||||||
|
"is-weakref": ["is-weakref@1.1.1", "http://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
|
||||||
|
|
||||||
|
"is-weakset": ["is-weakset@2.0.4", "http://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
|
||||||
|
|
||||||
|
"isarray": ["isarray@2.0.5", "http://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
|
||||||
|
|
||||||
|
"isexe": ["isexe@2.0.0", "http://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
|
"iterator.prototype": ["iterator.prototype@1.1.5", "http://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
|
||||||
|
|
||||||
|
"js-tokens": ["js-tokens@4.0.0", "http://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||||
|
|
||||||
|
"js-yaml": ["js-yaml@4.1.1", "http://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||||
|
|
||||||
|
"jsesc": ["jsesc@3.1.0", "http://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||||
|
|
||||||
|
"json-buffer": ["json-buffer@3.0.1", "http://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||||
|
|
||||||
|
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "http://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||||
|
|
||||||
|
"json-schema-traverse": ["json-schema-traverse@0.4.1", "http://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||||
|
|
||||||
|
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "http://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||||
|
|
||||||
|
"jsx-ast-utils": ["jsx-ast-utils@3.3.5", "http://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
|
||||||
|
|
||||||
|
"keyv": ["keyv@4.5.4", "http://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||||
|
|
||||||
|
"levn": ["levn@0.4.1", "http://registry.npmjs.org/levn/-/levn-0.4.1.tgz", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||||
|
|
||||||
|
"lightningcss": ["lightningcss@1.32.0", "http://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
|
|
||||||
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "http://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "http://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "http://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||||
|
|
||||||
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "http://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "http://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "http://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "http://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "http://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "http://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "http://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "http://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||||
|
|
||||||
|
"lines-and-columns": ["lines-and-columns@1.2.4", "http://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||||
|
|
||||||
|
"locate-path": ["locate-path@6.0.0", "http://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||||
|
|
||||||
|
"lodash": ["lodash@4.18.1", "http://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="],
|
||||||
|
|
||||||
|
"lodash.merge": ["lodash.merge@4.6.2", "http://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||||
|
|
||||||
|
"loose-envify": ["loose-envify@1.4.0", "http://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||||
|
|
||||||
|
"math-intrinsics": ["math-intrinsics@1.1.0", "http://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||||
|
|
||||||
|
"merge2": ["merge2@1.4.1", "http://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||||
|
|
||||||
|
"micromatch": ["micromatch@4.0.8", "http://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||||
|
|
||||||
|
"minimatch": ["minimatch@3.1.5", "http://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
|
"mrmime": ["mrmime@2.0.1", "http://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "http://registry.npmjs.org/ms/-/ms-2.1.3.tgz", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"nanoid": ["nanoid@3.3.11", "http://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
|
"natural-compare": ["natural-compare@1.4.0", "http://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||||
|
|
||||||
|
"node-addon-api": ["node-addon-api@7.1.1", "http://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||||
|
|
||||||
|
"node-exports-info": ["node-exports-info@1.6.0", "http://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="],
|
||||||
|
|
||||||
|
"object-assign": ["object-assign@4.1.1", "http://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||||
|
|
||||||
|
"object-inspect": ["object-inspect@1.13.4", "http://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||||
|
|
||||||
|
"object-keys": ["object-keys@1.1.1", "http://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
|
||||||
|
|
||||||
|
"object.assign": ["object.assign@4.1.7", "http://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
|
||||||
|
|
||||||
|
"object.entries": ["object.entries@1.1.9", "http://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
|
||||||
|
|
||||||
|
"object.fromentries": ["object.fromentries@2.0.8", "http://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
|
||||||
|
|
||||||
|
"object.values": ["object.values@1.2.1", "http://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
|
||||||
|
|
||||||
|
"optionator": ["optionator@0.9.4", "http://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||||
|
|
||||||
|
"own-keys": ["own-keys@1.0.1", "http://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
|
||||||
|
|
||||||
|
"p-limit": ["p-limit@3.1.0", "http://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||||
|
|
||||||
|
"p-locate": ["p-locate@5.0.0", "http://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||||
|
|
||||||
|
"parent-module": ["parent-module@1.0.1", "http://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||||
|
|
||||||
|
"parse-json": ["parse-json@5.2.0", "http://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||||
|
|
||||||
|
"path-exists": ["path-exists@4.0.0", "http://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||||
|
|
||||||
|
"path-key": ["path-key@3.1.1", "http://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"path-parse": ["path-parse@1.0.7", "http://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||||
|
|
||||||
|
"path-type": ["path-type@4.0.0", "http://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
|
||||||
|
|
||||||
|
"picocolors": ["picocolors@1.1.1", "http://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
|
"picomatch": ["picomatch@4.0.4", "http://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
||||||
|
|
||||||
|
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "http://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||||
|
|
||||||
|
"postcss": ["postcss@8.5.9", "http://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw=="],
|
||||||
|
|
||||||
|
"prelude-ls": ["prelude-ls@1.2.1", "http://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||||
|
|
||||||
|
"prop-types": ["prop-types@15.7.2", "http://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" } }, "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ=="],
|
||||||
|
|
||||||
|
"punycode": ["punycode@2.3.1", "http://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||||
|
|
||||||
|
"queue-microtask": ["queue-microtask@1.2.3", "http://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
|
|
||||||
|
"react": ["react@19.2.5", "http://registry.npmjs.org/react/-/react-19.2.5.tgz", {}, "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA=="],
|
||||||
|
|
||||||
|
"react-dom": ["react-dom@19.2.5", "http://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.5" } }, "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag=="],
|
||||||
|
|
||||||
|
"react-is": ["react-is@19.2.5", "http://registry.npmjs.org/react-is/-/react-is-19.2.5.tgz", {}, "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ=="],
|
||||||
|
|
||||||
|
"react-transition-group": ["react-transition-group@4.4.5", "http://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
|
||||||
|
|
||||||
|
"readdirp": ["readdirp@4.1.2", "http://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||||
|
|
||||||
|
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "http://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
|
||||||
|
|
||||||
|
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "http://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
|
||||||
|
|
||||||
|
"reselect": ["reselect@5.1.1", "http://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
|
||||||
|
|
||||||
|
"resolve": ["resolve@2.0.0-next.6", "http://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
|
||||||
|
|
||||||
|
"resolve-from": ["resolve-from@4.0.0", "http://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||||
|
|
||||||
|
"reusify": ["reusify@1.1.0", "http://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||||
|
|
||||||
|
"rolldown": ["rolldown@1.0.0-rc.15", "http://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="],
|
||||||
|
|
||||||
|
"run-parallel": ["run-parallel@1.2.0", "http://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||||
|
|
||||||
|
"safe-array-concat": ["safe-array-concat@1.1.3", "http://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
|
||||||
|
|
||||||
|
"safe-push-apply": ["safe-push-apply@1.0.0", "http://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
|
||||||
|
|
||||||
|
"safe-regex-test": ["safe-regex-test@1.1.0", "http://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
|
||||||
|
|
||||||
|
"sass": ["sass@1.99.0", "http://registry.npmjs.org/sass/-/sass-1.99.0.tgz", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": "sass.js" }, "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q=="],
|
||||||
|
|
||||||
|
"scheduler": ["scheduler@0.27.0", "http://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||||
|
|
||||||
|
"semver": ["semver@6.3.1", "http://registry.npmjs.org/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
|
"set-function-length": ["set-function-length@1.2.2", "http://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
|
||||||
|
|
||||||
|
"set-function-name": ["set-function-name@2.0.2", "http://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
|
||||||
|
|
||||||
|
"set-proto": ["set-proto@1.0.0", "http://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
|
||||||
|
|
||||||
|
"shebang-command": ["shebang-command@2.0.0", "http://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"shebang-regex": ["shebang-regex@3.0.0", "http://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
|
"side-channel": ["side-channel@1.1.0", "http://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||||
|
|
||||||
|
"side-channel-list": ["side-channel-list@1.0.1", "http://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
|
||||||
|
|
||||||
|
"side-channel-map": ["side-channel-map@1.0.1", "http://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||||
|
|
||||||
|
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "http://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||||
|
|
||||||
|
"sirv": ["sirv@3.0.2", "http://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
||||||
|
|
||||||
|
"source-map": ["source-map@0.5.7", "http://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
|
||||||
|
|
||||||
|
"source-map-js": ["source-map-js@1.2.1", "http://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
|
"stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "http://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
|
||||||
|
|
||||||
|
"string.prototype.matchall": ["string.prototype.matchall@4.0.12", "http://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
|
||||||
|
|
||||||
|
"string.prototype.repeat": ["string.prototype.repeat@1.0.0", "http://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
|
||||||
|
|
||||||
|
"string.prototype.trim": ["string.prototype.trim@1.2.10", "http://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
|
||||||
|
|
||||||
|
"string.prototype.trimend": ["string.prototype.trimend@1.0.9", "http://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
|
||||||
|
|
||||||
|
"string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "http://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
|
||||||
|
|
||||||
|
"strip-json-comments": ["strip-json-comments@3.1.1", "http://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||||
|
|
||||||
|
"stylis": ["stylis@4.2.0", "http://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
|
||||||
|
|
||||||
|
"supports-color": ["supports-color@7.2.0", "http://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||||
|
|
||||||
|
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "http://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||||
|
|
||||||
|
"tinyglobby": ["tinyglobby@0.2.16", "http://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
|
||||||
|
|
||||||
|
"to-regex-range": ["to-regex-range@5.0.1", "http://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||||
|
|
||||||
|
"totalist": ["totalist@3.0.1", "http://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||||
|
|
||||||
|
"ts-api-utils": ["ts-api-utils@2.5.0", "http://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
|
||||||
|
|
||||||
|
"tslib": ["tslib@2.8.1", "http://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
|
"type-check": ["type-check@0.4.0", "http://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||||
|
|
||||||
|
"typed-array-buffer": ["typed-array-buffer@1.0.3", "http://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
|
||||||
|
|
||||||
|
"typed-array-byte-length": ["typed-array-byte-length@1.0.3", "http://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
|
||||||
|
|
||||||
|
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "http://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
|
||||||
|
|
||||||
|
"typed-array-length": ["typed-array-length@1.0.7", "http://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@6.0.2", "http://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
||||||
|
|
||||||
|
"unbox-primitive": ["unbox-primitive@1.1.0", "http://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||||
|
|
||||||
|
"uri-js": ["uri-js@4.4.1", "http://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||||
|
|
||||||
|
"use-sync-external-store": ["use-sync-external-store@1.6.0", "http://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
|
||||||
|
|
||||||
|
"vite": ["vite@8.0.8", "http://registry.npmjs.org/vite/-/vite-8.0.8.tgz", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="],
|
||||||
|
|
||||||
|
"vite-plugin-symfony": ["vite-plugin-symfony@8.2.4", "http://registry.npmjs.org/vite-plugin-symfony/-/vite-plugin-symfony-8.2.4.tgz", { "dependencies": { "debug": "^4.4.1", "fast-glob": "^3.3.3", "picocolors": "^1.1.1", "sirv": "^3.0.1" }, "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-ph98EMPx8FhA6QIp43ZiK0zjODV9jumB7EHXfZEhRme2lo9oBa9sAXCNCCIvdVk/m9EWkNZpcRBjequjXZiSuA=="],
|
||||||
|
|
||||||
|
"which": ["which@2.0.2", "http://registry.npmjs.org/which/-/which-2.0.2.tgz", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
|
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "http://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
||||||
|
|
||||||
|
"which-builtin-type": ["which-builtin-type@1.2.1", "http://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
|
||||||
|
|
||||||
|
"which-collection": ["which-collection@1.0.2", "http://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
|
||||||
|
|
||||||
|
"which-typed-array": ["which-typed-array@1.1.20", "http://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
|
||||||
|
|
||||||
|
"word-wrap": ["word-wrap@1.2.5", "http://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||||
|
|
||||||
|
"yaml": ["yaml@1.10.3", "http://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", {}, "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA=="],
|
||||||
|
|
||||||
|
"yocto-queue": ["yocto-queue@0.1.0", "http://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||||
|
|
||||||
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "http://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc/globals": ["globals@14.0.0", "http://registry.npmjs.org/globals/-/globals-14.0.0.tgz", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||||
|
|
||||||
|
"@mui/material/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@mui/private-theming/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@mui/styled-engine/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@mui/system/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@mui/utils/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@mui/x-charts/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "http://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "http://registry.npmjs.org/semver/-/semver-7.7.4.tgz", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "http://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
|
"babel-plugin-macros/resolve": ["resolve@1.22.12", "http://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-react/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"fast-glob/glob-parent": ["glob-parent@5.1.2", "http://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
|
"hoist-non-react-statics/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"micromatch/picomatch": ["picomatch@2.3.2", "http://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||||
|
|
||||||
|
"prop-types/react-is": ["react-is@16.11.0", "http://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz", {}, "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw=="],
|
||||||
|
|
||||||
|
"react-transition-group/prop-types": ["prop-types@15.8.1", "http://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||||
|
|
||||||
|
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "http://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="],
|
||||||
|
|
||||||
|
"@mui/material/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@mui/private-theming/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@mui/styled-engine/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@mui/system/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@mui/utils/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@mui/x-charts/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.5", "http://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
|
||||||
|
|
||||||
|
"eslint-plugin-react/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"react-transition-group/prop-types/react-is": ["react-is@16.13.1", "http://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "http://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
115
compose.yaml
Normal file
115
compose.yaml
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: '${APP_NAME}-app'
|
||||||
|
ports:
|
||||||
|
- "10080:80"
|
||||||
|
environment:
|
||||||
|
SERVER_NAME: ${SERVER_NAME:-:80}
|
||||||
|
APP_ENV: prod
|
||||||
|
APP_SECRET: ${APP_SECRET}
|
||||||
|
DATABASE_URL: >-
|
||||||
|
postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?serverVersion=${POSTGRES_VERSION}&charset=utf8
|
||||||
|
POSTGRES_URL: db
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
MERCURE_URL: http://localhost/.well-known/mercure
|
||||||
|
MERCURE_PUBLIC_URL: https://${APP_PUBLIC_HOSTNAME:-localhost}/.well-known/mercure
|
||||||
|
MERCURE_JWT_SECRET: ${MERCURE_JWT_SECRET}
|
||||||
|
MERCURE_JWT_TOKEN: ${MERCURE_JWT_TOKEN}
|
||||||
|
MERCURE_SUBSCRIBER_JWT: ${MERCURE_SUBSCRIBER_JWT}
|
||||||
|
MAILER_DSN: smtp://mail:25?verify_peer=0
|
||||||
|
RECAPTCHA_SITE_KEY: ${RECAPTCHA_SITE_KEY}
|
||||||
|
RECAPTCHA_SECRET_KEY: ${RECAPTCHA_SECRET_KEY}
|
||||||
|
WEBAUTHN_RP_ID: ${WEBAUTHN_RP_ID:-localhost}
|
||||||
|
WEBAUTHN_ORIGIN: ${WEBAUTHN_ORIGIN:-https://localhost}
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||||
|
MINIO_ENDPOINT: http://minio:9000
|
||||||
|
MINIO_PUBLIC_URL: ${MINIO_PUBLIC_URL:-http://localhost:9000}
|
||||||
|
volumes:
|
||||||
|
- app_var:/app/var
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
mail:
|
||||||
|
condition: service_started
|
||||||
|
minio:
|
||||||
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: '${APP_NAME}-minio'
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
|
- "9001:9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- minio_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 10s
|
||||||
|
minio_init:
|
||||||
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1
|
||||||
|
restart: "no"
|
||||||
|
container_name: '${APP_NAME}-minio-init'
|
||||||
|
depends_on:
|
||||||
|
minio:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./docker/minio-init.sh:/minio-init.sh:ro
|
||||||
|
entrypoint: ["/bin/sh", "/minio-init.sh"]
|
||||||
|
mail:
|
||||||
|
image: boky/postfix:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: '${APP_NAME}-mail'
|
||||||
|
hostname: postfix.mail.${MAIL_DOMAIN:-localhost}
|
||||||
|
environment:
|
||||||
|
ALLOWED_SENDER_DOMAINS: ${MAIL_DOMAIN:-localhost}
|
||||||
|
HOSTNAME: postfix.mail.${MAIL_DOMAIN:-localhost}
|
||||||
|
POSTFIX_myhostname: postfix.mail.${MAIL_DOMAIN:-localhost}
|
||||||
|
POSTFIX_mynetworks: "127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"
|
||||||
|
POSTFIX_smtpd_tls_security_level: none
|
||||||
|
RELAYHOST: ${MAIL_RELAYHOST:-}
|
||||||
|
RELAYHOST_AUTH: ${MAIL_RELAYHOST_AUTH:-}
|
||||||
|
RELAYHOST_PASSWORD: ${MAIL_RELAYHOST_PASSWORD:-}
|
||||||
|
volumes:
|
||||||
|
- postfix_spool:/var/spool/postfix
|
||||||
|
db:
|
||||||
|
image: postgres:${POSTGRES_VERSION:-18}-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: '${APP_NAME}-db'
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}" ]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 10
|
||||||
|
start_period: 10s
|
||||||
|
ports:
|
||||||
|
- "15432:5432"
|
||||||
|
volumes:
|
||||||
|
app_var:
|
||||||
|
postgres_data:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
postfix_spool:
|
||||||
|
minio_data:
|
||||||
127
composer.json
127
composer.json
@@ -1,73 +1,94 @@
|
|||||||
{
|
{
|
||||||
"name": "root/mine",
|
|
||||||
"license": "proprietary",
|
|
||||||
"type": "project",
|
"type": "project",
|
||||||
|
"license": "proprietary",
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.5",
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"doctrine/dbal": "^3.7",
|
||||||
|
"doctrine/doctrine-bundle": ">=2.11 <2.14",
|
||||||
|
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||||
|
"doctrine/orm": "^2.6",
|
||||||
|
"endroid/qr-code": "^6.1",
|
||||||
|
"league/flysystem-aws-s3-v3": "^3.0",
|
||||||
|
"league/flysystem-bundle": "^3.6",
|
||||||
|
"liip/imagine-bundle": "^2.13",
|
||||||
|
"pentatrion/vite-bundle": "^8.2",
|
||||||
|
"scheb/2fa-backup-code": "^8.5",
|
||||||
|
"scheb/2fa-bundle": "^8.5",
|
||||||
|
"scheb/2fa-totp": "^8.5",
|
||||||
|
"symfony/console": "7.4.*",
|
||||||
|
"symfony/flex": "^2.10.0",
|
||||||
|
"symfony/form": "7.4.*",
|
||||||
|
"symfony/framework-bundle": "7.4.*",
|
||||||
|
"symfony/http-client": "7.4.*",
|
||||||
|
"symfony/mailer": "7.4.*",
|
||||||
|
"symfony/mercure": "^0.6",
|
||||||
|
"symfony/mercure-bundle": "*",
|
||||||
|
"symfony/monolog-bundle": "^3.8",
|
||||||
|
"symfony/security-bundle": "7.4.*",
|
||||||
|
"symfony/translation": "7.4.*",
|
||||||
|
"symfony/twig-bundle": "7.4.*",
|
||||||
|
"symfony/validator": "7.4.*",
|
||||||
|
"symfony/yaml": "7.4.*",
|
||||||
|
"web-auth/webauthn-framework": "^5.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"firebase/php-jwt": "^7.0",
|
||||||
|
"roave/security-advisories": "dev-master",
|
||||||
|
"symfony/dotenv": "7.4.*",
|
||||||
|
"symfony/maker-bundle": "^1.5",
|
||||||
|
"symfony/stopwatch": "7.4.*",
|
||||||
|
"symfony/web-profiler-bundle": "7.4.*"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"preferred-install": {
|
||||||
|
"*": "dist"
|
||||||
|
},
|
||||||
|
"sort-packages": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"symfony/flex": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"": "src/"
|
"App\\": "src/"
|
||||||
},
|
}
|
||||||
"classmap": [
|
|
||||||
"app/AppKernel.php",
|
|
||||||
"app/AppCache.php"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Tests\\": "tests/"
|
"App\\Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"replace": {
|
||||||
"php": ">=7.3",
|
"symfony/polyfill-iconv": "*",
|
||||||
"symfony/symfony": "3.*",
|
"symfony/polyfill-ctype": "*",
|
||||||
"doctrine/orm": "^2.6",
|
"symfony/polyfill-php73": "*",
|
||||||
"doctrine/doctrine-bundle": "^1.6",
|
"symfony/polyfill-php72": "*",
|
||||||
"doctrine/doctrine-cache-bundle": "^1.3",
|
"symfony/polyfill-php71": "*",
|
||||||
"symfony/swiftmailer-bundle": "^2.3",
|
"symfony/polyfill-php70": "*",
|
||||||
"symfony/monolog-bundle": "^2.8",
|
"symfony/polyfill-php56": "*"
|
||||||
"symfony/polyfill-apcu": "^1.0",
|
|
||||||
"sensio/distribution-bundle": "^5.0",
|
|
||||||
"sensio/framework-extra-bundle": "^3.0.2",
|
|
||||||
"incenteev/composer-parameter-handler": "^2.0",
|
|
||||||
"gos/web-socket-bundle": "^1.8",
|
|
||||||
"friendsofsymfony/user-bundle": "~2.0@dev",
|
|
||||||
"doctrine/doctrine-migrations-bundle": "^1.0",
|
|
||||||
"symfony/assetic-bundle": "^2.8",
|
|
||||||
"predis/predis": "^1.0",
|
|
||||||
"snc/redis-bundle": "^2.0",
|
|
||||||
"hwi/oauth-bundle": "^0.5.1",
|
|
||||||
"cleentfaar/slack-bundle": "^0.20.1",
|
|
||||||
"ext-json": "*"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"roave/security-advisories": "dev-master",
|
|
||||||
"sensio/generator-bundle": "^3.0",
|
|
||||||
"symfony/phpunit-bridge": "^3.0"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"symfony-scripts": [
|
"auto-scripts": {
|
||||||
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
|
"cache:clear": "symfony-cmd",
|
||||||
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
|
"assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
|
||||||
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
|
},
|
||||||
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
|
|
||||||
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
|
|
||||||
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
|
|
||||||
],
|
|
||||||
"post-install-cmd": [
|
"post-install-cmd": [
|
||||||
"@symfony-scripts"
|
"@auto-scripts"
|
||||||
],
|
],
|
||||||
"post-update-cmd": [
|
"post-update-cmd": [
|
||||||
"@symfony-scripts"
|
"@auto-scripts"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/symfony": "*",
|
||||||
|
"doctrine/persistence": "<1.3"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"symfony-app-dir": "app",
|
"symfony": {
|
||||||
"symfony-bin-dir": "bin",
|
"allow-contrib": false,
|
||||||
"symfony-var-dir": "var",
|
"require": "7.4.*"
|
||||||
"symfony-web-dir": "web",
|
|
||||||
"symfony-tests-dir": "tests",
|
|
||||||
"symfony-assets-install": "relative",
|
|
||||||
"incenteev-parameters": {
|
|
||||||
"file": "app/config/parameters.yml"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12078
composer.lock
generated
12078
composer.lock
generated
File diff suppressed because it is too large
Load Diff
19
config/bundles.php
Normal file
19
config/bundles.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
|
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||||
|
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
|
||||||
|
Pentatrion\ViteBundle\PentatrionViteBundle::class => ['all' => true],
|
||||||
|
Webauthn\Bundle\WebauthnBundle::class => ['all' => true],
|
||||||
|
Webauthn\Stimulus\WebauthnStimulusBundle::class => ['all' => true],
|
||||||
|
Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
|
||||||
|
League\FlysystemBundle\FlysystemBundle::class => ['all' => true],
|
||||||
|
Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
|
||||||
|
];
|
||||||
11
config/packages/csrf.yaml
Normal file
11
config/packages/csrf.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Enable stateless CSRF protection for forms and logins/logouts
|
||||||
|
framework:
|
||||||
|
form:
|
||||||
|
csrf_protection:
|
||||||
|
token_id: submit
|
||||||
|
|
||||||
|
csrf_protection:
|
||||||
|
stateless_token_ids:
|
||||||
|
- submit
|
||||||
|
- authenticate
|
||||||
|
- logout
|
||||||
19
config/packages/dev/monolog.yaml
Normal file
19
config/packages/dev/monolog.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: stream
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: error
|
||||||
|
channels: [ "!event" ]
|
||||||
|
# uncomment to get logging in your browser
|
||||||
|
# you may have to allow bigger header sizes in your Web server configuration
|
||||||
|
#firephp:
|
||||||
|
# type: firephp
|
||||||
|
# level: info
|
||||||
|
#chromephp:
|
||||||
|
# type: chromephp
|
||||||
|
# level: info
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: [ "!event", "!doctrine", "!console" ]
|
||||||
3
config/packages/dev/routing.yaml
Normal file
3
config/packages/dev/routing.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
framework:
|
||||||
|
router:
|
||||||
|
strict_requirements: true
|
||||||
6
config/packages/dev/web_profiler.yaml
Normal file
6
config/packages/dev/web_profiler.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
web_profiler:
|
||||||
|
toolbar: true
|
||||||
|
intercept_redirects: false
|
||||||
|
|
||||||
|
framework:
|
||||||
|
profiler: { only_exceptions: false }
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user