Add Pezkuwi SDK UI - Polkadot.js Apps clone

- Clone Polkadot.js Apps repository
- Update package.json with Pezkuwi branding
- Add Pezkuwi endpoint to production chains (wss://pezkuwichain.app:9944)
- Create comprehensive README for SDK UI
- Set up project structure with all packages

Next steps:
- Apply Kurdistan colors (Kesk, Sor, Zer, Spi + Black) to UI theme
- Replace logos with Pezkuwi branding
- Test build and deployment
This commit is contained in:
Claude
2025-11-14 00:55:17 +00:00
parent c48ded7ff2
commit c71ddb6e0d
5836 changed files with 324981 additions and 17 deletions
@@ -0,0 +1,52 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DropdownOptions } from '../util/types.js';
import type { ConstValueBase } from './types.js';
import React from 'react';
import Dropdown from '../Dropdown.js';
import { filterDropdownItems } from '../util/index.js';
interface Props {
className?: string;
isError?: boolean;
onChange: (value: ConstValueBase) => void;
options: DropdownOptions;
value: ConstValueBase;
}
function transform ({ value }: Props): (method: string) => ConstValueBase {
return (method: string): ConstValueBase => {
const section = value.section;
return {
method,
section
};
};
}
function SelectKey (props: Props): React.ReactElement<Props> | null {
const { className = '', isError, onChange, options, value } = props;
if (!options.length) {
return null;
}
return (
<Dropdown
className={`${className} ui--DropdownLinked-Items`}
isError={isError}
onChange={onChange}
onSearch={filterDropdownItems}
options={options}
transform={transform(props)}
value={value.method}
withLabel={false}
/>
);
}
export default React.memo(SelectKey);
@@ -0,0 +1,36 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DropdownOptions } from '../util/types.js';
import type { ConstValueBase, StorageEntryPromise } from './types.js';
import React from 'react';
import Dropdown from '../Dropdown.js';
import { filterDropdownItems } from '../util/index.js';
interface Props {
className?: string;
defaultValue?: StorageEntryPromise;
isError?: boolean;
onChange: (value: string) => void;
options: DropdownOptions;
value: ConstValueBase;
}
function SelectSection ({ className = '', defaultValue, isError, onChange, options, value: { section } }: Props): React.ReactElement<Props> {
return (
<Dropdown
className={`${className} ui--DropdownLinked-Sections`}
defaultValue={defaultValue}
isError={isError}
onChange={onChange}
onSearch={filterDropdownItems}
options={options}
value={section}
withLabel={false}
/>
);
}
export default React.memo(SelectSection);
@@ -0,0 +1,95 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ApiPromise } from '@polkadot/api';
import type { ConstantCodec } from '@polkadot/types/metadata/decorate/types';
import type { DropdownOptions } from '../util/types.js';
import type { ConstValue, ConstValueBase } from './types.js';
import React, { useCallback, useState } from 'react';
import { useApi } from '@polkadot/react-hooks';
import LinkedWrapper from '../InputExtrinsic/LinkedWrapper.js';
import keyOptions from './options/key.js';
import sectionOptions from './options/section.js';
import SelectKey from './SelectKey.js';
import SelectSection from './SelectSection.js';
interface Props {
className?: string;
defaultValue: ConstValueBase;
isError?: boolean;
label: React.ReactNode;
onChange?: (value: ConstValue) => void;
withLabel?: boolean;
}
function getValue (api: ApiPromise, { method, section }: ConstValueBase): ConstValue {
const firstSec = Object.keys(api.consts)[0];
const firstMet = Object.keys(api.consts[firstSec])[0];
const value = api.consts[section]?.[method]
? { method, section }
: { method: firstMet, section: firstSec };
return {
...value,
meta: (api.consts[value.section][value.method] as ConstantCodec).meta
};
}
function InputConsts ({ className = '', defaultValue, label, onChange, withLabel }: Props): React.ReactElement<Props> {
const { api } = useApi();
const [optionsMethod, setOptionsMethod] = useState<DropdownOptions>(() => keyOptions(api, defaultValue.section));
const [optionsSection] = useState<DropdownOptions>(() => sectionOptions(api));
const [value, setValue] = useState<ConstValue>(() => getValue(api, defaultValue));
const _onKeyChange = useCallback(
(newValue: ConstValueBase): void => {
if (value.section !== newValue.section || value.method !== newValue.method) {
const { method, section } = newValue;
const meta = (api.consts[section][method] as ConstantCodec).meta;
const updated = { meta, method, section };
setValue(updated);
onChange && onChange(updated);
}
},
[api, onChange, value]
);
const _onSectionChange = useCallback(
(newSection: string): void => {
if (newSection !== value.section) {
const optionsMethod = keyOptions(api, newSection);
setOptionsMethod(optionsMethod);
_onKeyChange({ method: optionsMethod[0].value, section: newSection });
}
},
[_onKeyChange, api, value]
);
return (
<LinkedWrapper
className={className}
label={label}
withLabel={withLabel}
>
<SelectSection
className='small'
onChange={_onSectionChange}
options={optionsSection}
value={value}
/>
<SelectKey
className='large'
onChange={_onKeyChange}
options={optionsMethod}
value={value}
/>
</LinkedWrapper>
);
}
export default React.memo(InputConsts);
@@ -0,0 +1,46 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ApiPromise } from '@polkadot/api';
import type { ConstantCodec } from '@polkadot/types/metadata/decorate/types';
import type { DropdownOption, DropdownOptions } from '../../util/types.js';
import React from 'react';
import { getSiName } from '@polkadot/types/metadata/util';
export default function createOptions (api: ApiPromise, sectionName: string): DropdownOptions {
const section = api.consts[sectionName];
if (!section || Object.keys(section).length === 0) {
return [];
}
return Object
.keys(section)
.filter((s) => !s.startsWith('$'))
.sort()
.map((value): DropdownOption => {
const method = (section[value] as ConstantCodec);
return {
className: 'ui--DropdownLinked-Item',
key: `${sectionName}_${value}`,
text: [
<div
className='ui--DropdownLinked-Item-call'
key={`${sectionName}_${value}:call`}
>
{value}: {getSiName(api.registry.lookup, method.meta.type)}
</div>,
<div
className='ui--DropdownLinked-Item-text'
key={`${sectionName}_${value}:text`}
>
{(method.meta.docs[0] || method.meta.name).toString()}
</div>
],
value
};
});
}
@@ -0,0 +1,17 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ApiPromise } from '@polkadot/api';
import type { DropdownOptions } from '../../util/types.js';
export default function createOptions (api: ApiPromise): DropdownOptions {
return Object
.keys(api.consts)
.filter((s) => !s.startsWith('$'))
.sort()
.filter((name): number => Object.keys(api.consts[name]).length)
.map((name): { text: string; value: string } => ({
text: name,
value: name
}));
}
@@ -0,0 +1,17 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { StorageEntryBase } from '@polkadot/api/types';
import type { PalletConstantMetadataLatest } from '@polkadot/types/interfaces';
import type { AnyTuple } from '@polkadot/types/types';
export type StorageEntryPromise = StorageEntryBase<'promise', any, AnyTuple>;
export interface ConstValueBase {
method: string;
section: string;
}
export interface ConstValue extends ConstValueBase {
meta: PalletConstantMetadataLatest;
}
@@ -0,0 +1,10 @@
// Copyright 2017-2025 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
export class TokenUnit {
public static abbr = 'Unit';
public static setAbbr (abbr: string = TokenUnit.abbr): void {
TokenUnit.abbr = abbr;
}
}