npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

solid-panorama-runtime

v0.5.1

Published

Solid.js runtime for Valve's Panorama UI (for Dota 2 Custom Games).

Downloads

140

Readme

Solid.js for Valve's Panorama UI

简体中文

Before using this library, you need to learn SolidJS.

At present, it can be used normally. Please refer to solid-panorama-example.

The compiler has been modified and the API of panorama has been optimized.
For example, adding attribute and parent element to createElement greatly reduces the number of API calls and solves the problem that $. CreatePanelWithProperties cannot be called.

Installation

yarn add solid-js \
         solid-panorama-runtime \
         babel-plugin-jsx-panorama-expressions \
         babel-preset-solid-panorama

Usage

babel.config.js

module.exports = {
    targets: 'node 18.12',
    presets: [
        '@babel/preset-env',
        '@babel/preset-typescript',
        [
            'babel-preset-solid-panorama',
            {
                moduleName: 'solid-panorama-runtime',
                generate: 'universal'
            }
        ]
    ],
    plugins: ['@babel/plugin-transform-typescript']
};

app.tsx

import { onMount } from 'solid-js';
import { render } from 'solid-panorama-runtime';

function HelloWorld() {
    let root: Panel | undefined;
    onMount(() => {
        $.Msg(root);
    });
    return <Panel ref={root}>Hello World!</Panel>;
}

render(() => <HelloWorld />, $('#app'));

About react-panorama

Thanks to ark120202 for creating react-panorama, some of the code for this project was copied from react-panorama and adapted.

Optional Features

style

The style is compatible. If the style is a string, an error will pop up if the semicolon is not written at the end of the style. Therefore, the semicolon will be automatically added to the parsing during compilation.

When style is Object, some attributes can be assigned numbers, which will be automatically converted to px. The support list can be viewed:packages/runtime/src/config.ts

class

Both class and className properties are supported, and since solid.js provides classList properties that can be added dynamically by true | false, it also provides similar functionality, and all three properties can exist at the same time.

<Button
    class={current() === 'foo' ? 'selected' : ''}
    onClick={() => setCurrent('foo')}
>
    foo
</Button>

<Button
  class="my-button"
  classList={{selected: current() === 'foo'}}
  onClick={() => setCurrent('foo')}
>foo</Button>

Event

Not support bubble event.

The event is optimized. The first parameter of the event callback is the element itself.

Support Text Node

In cases like <div> Hi </div> in HTML Hi will be rendered as a text node, i.e. textNode.

The text node will automatically create Label and enable html rendering by default, if it contains HTML tags, you need to use string.

Note that if the text is the text that begins with #, such as #addon_game_name, such will automatically call $.Localize, but can not be mixed with other text.

For example, the following is the correct way to write it:

// plain text
<Panel>
    Welcome My Game
</Panel>

// includes html tag
<Panel>
    {`<strong>Welcome</strong> My Game`}
</Panel>

// multiple text
<Panel>
    <Label text="Welcome" />
    #addon_game_name
    <Label text="(~ ̄▽ ̄)~" />
</Panel>

Custom Attribites

snippet

Type: string

Auto load snippet

<Panel snippet="MyBtton" />

vars and dialogVariables

Type: Record<string, string | number | Date>

Both are the same, dialogVariables is for compatibility ark120202/react-panorama

  • When value is string, call SetDialogVariable, if value start width # then call SetDialogVariableLocString
  • When value is number, call SetDialogVariableInt
  • When value is Date, call SetDialogVariableTime

Some adjustments have been made for Label, vars and dialogVariables will be written first and after set to Label.text, if the text starts with # it will call $.Localize(text, Label)

<Label vars={{ name: '#addon_game_name' }} text="Welcome {d:name}" />

attrs

Type: Record<string, string | number>

  • When value is string, callSetAttributeString
  • When value is number, callSetAttributeInt
<Panel attrs={{ name: 'my name' }} />

data-*

Support data-* property, note that here is different from HTML, the data-* properties are stored in Panel.Data(), so you can easily store JS data objects, for example data-list={['name']}, then you can get the value by Panel.Data()['list'][0].

<Panel data-my-data={{ name: 'my name' }} />

tooltip_text

Type: string

Auto setting onmouseover="DOTAShowTextTooltip(<token>)"onmouseout="DOTAHideTextTooltip()"

Note: Cannot coexist with onmouseover and onmouseout events

<Panel tooltip_text="#addon_game_name" />

custom_tooltip

Type: [string, string]

[<tooltip name>, <xml file path>]

Auto setting onmouseover="UIShowCustomLayoutParametersTooltip()"onmouseout="UIHideCustomLayoutTooltip()"

Note: Cannot coexist with onmouseover and onmouseout events

<Panel custom_tooltip={['Item', 'file://{resources}/layout/custom_game/tooltip_example.xml']} custom_tooltip_params={{ name: 'item_xxx' }} />
// OR
<Panel custom_tooltip={['Item', 'tooltip_example']} custom_tooltip_params={{ name: 'item_xxx' }} />

custom_tooltip_params

Type: Record<string, string | number>

Drag events

onDragStart?: (source: Panel, dragCallbacks: IDragCallbacks) => void;
onDragEnd?: (source: Panel, draggedPanel: Panel) => void;
onDragEnter?: (source: Panel, draggedPanel: Panel) => void;
onDragDrop?: (source: Panel, draggedPanel: Panel) => void;
onDragLeave?: (source: Panel, draggedPanel: Panel) => void;

If listen onDragStart, SetDraggable(true) will be called automatically, so the draggable property can be ignored.

function onItemDragStart(source: Panel, dragCallbacks: IDragCallbacks) {
    // ...
}

<Panel onDragStart={onItemDragStart} />;

NOTES

import { children, splitProps } from 'solid-js';

interface MyButtonProps {
    children?: JSX.Element;
}

function MyButton({ className, ...props }: MyButtonProps) {
    const [local, others] = splitProps(props, ['children']);
    // Note that if your children have a fixed layout and are not changing, you should use `{local.children}` directly.
    const resolved = children(() => local.children);

    createEffect(() => {
        const list = resolved.toArray();
        for (const [index, child] of list.entries()) {
            (child as Panel).SetHasClass(
                'LastChild',
                index === list.length - 1
            );
        }
    });

    return (
        <Button className={className || 'ButtonBevel'} {...others}>
            {resolved()}
        </Button>
    );
}
  • Try not to use object spread syntax for the arguments of function components, this syntax will make it impossible to update properties, if you need to split props, you should use splitProps.
import { splitProps } from 'solid-js';

// ✅ Recommend
function MyButton(props: MyButtonProps) {
    const [local, others] = splitProps(props, ['class', 'children']);
    return (
        <Button class={local.class + ' MyButtonStyle'} {...others}>
            <Label text={local.class} />
        </Button>
    );
}

// 😞 This is not recommended,
// even if the properties are not split,
// the properties will not be updated.
function MyButton({ ...props }: MyButtonProps);
  • UI focus issues

The UI by default will cause focus to be obtained if any element is clicked on, which will cause shortcuts etc. to be disabled, and generally there is no need to focus on elements of the UI, so any element will call SetDisableFocusOnMouseDown(true) when it is created.